forked from OSchip/llvm-project
Overhaul Cell SPU's addressing mode internals so that there are now
only two addressing mode nodes, SPUaform and SPUindirect (vice the three previous ones, SPUaform, SPUdform and SPUxform). This improves code somewhat because we now avoid using reg+reg addressing when it can be avoided. It also simplifies the address selection logic, which was the main point for doing this. Also, for various global variables that would be loaded using SPU's A-form addressing, prefer D-form offs[reg] addressing, keeping the base in a register if the variable is used more than once. llvm-svn: 46483
This commit is contained in:
parent
ce0740e1f5
commit
ceae3bbf4d
|
|
@ -195,12 +195,18 @@ namespace {
|
||||||
void
|
void
|
||||||
printAddr256K(const MachineInstr *MI, unsigned OpNo)
|
printAddr256K(const MachineInstr *MI, unsigned OpNo)
|
||||||
{
|
{
|
||||||
/* Note: operand 1 is an offset or symbol name. Operand 2 is
|
/* Note: operand 1 is an offset or symbol name. */
|
||||||
ignored. */
|
|
||||||
if (MI->getOperand(OpNo).isImmediate()) {
|
if (MI->getOperand(OpNo).isImmediate()) {
|
||||||
printS16ImmOperand(MI, OpNo);
|
printS16ImmOperand(MI, OpNo);
|
||||||
} else {
|
} else {
|
||||||
printOp(MI->getOperand(OpNo));
|
printOp(MI->getOperand(OpNo));
|
||||||
|
if (MI->getOperand(OpNo+1).isImmediate()) {
|
||||||
|
int displ = int(MI->getOperand(OpNo+1).getImm());
|
||||||
|
if (displ > 0)
|
||||||
|
O << "+" << displ;
|
||||||
|
else if (displ < 0)
|
||||||
|
O << displ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,7 +315,6 @@ void SPUAsmPrinter::printOp(const MachineOperand &MO) {
|
||||||
case MachineOperand::MO_JumpTableIndex:
|
case MachineOperand::MO_JumpTableIndex:
|
||||||
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
|
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
|
||||||
<< '_' << MO.getIndex();
|
<< '_' << MO.getIndex();
|
||||||
// FIXME: PIC relocation model
|
|
||||||
return;
|
return;
|
||||||
case MachineOperand::MO_ConstantPoolIndex:
|
case MachineOperand::MO_ConstantPoolIndex:
|
||||||
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
|
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
|
||||||
|
|
@ -521,7 +526,8 @@ bool LinuxAsmPrinter::doFinalization(Module &M) {
|
||||||
O << "\t.zero\t" << Size;
|
O << "\t.zero\t" << Size;
|
||||||
} else if (I->hasInternalLinkage()) {
|
} else if (I->hasInternalLinkage()) {
|
||||||
SwitchToDataSection("\t.data", I);
|
SwitchToDataSection("\t.data", I);
|
||||||
O << TAI->getLCOMMDirective() << name << "," << Size << "," << Align;
|
O << ".local " << name << "\n";
|
||||||
|
O << TAI->getCOMMDirective() << name << "," << Size << "," << Align << "\n";
|
||||||
} else {
|
} else {
|
||||||
SwitchToDataSection("\t.data", I);
|
SwitchToDataSection("\t.data", I);
|
||||||
O << ".comm " << name << "," << Size;
|
O << ".comm " << name << "," << Size;
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,16 @@ namespace {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isHighLow(const SDOperand &Op)
|
||||||
|
{
|
||||||
|
return (Op.getOpcode() == SPUISD::IndirectAddr
|
||||||
|
&& ((Op.getOperand(0).getOpcode() == SPUISD::Hi
|
||||||
|
&& Op.getOperand(1).getOpcode() == SPUISD::Lo)
|
||||||
|
|| (Op.getOperand(0).getOpcode() == SPUISD::Lo
|
||||||
|
&& Op.getOperand(1).getOpcode() == SPUISD::Hi)));
|
||||||
|
}
|
||||||
|
|
||||||
//===------------------------------------------------------------------===//
|
//===------------------------------------------------------------------===//
|
||||||
//! MVT::ValueType to "useful stuff" mapping structure:
|
//! MVT::ValueType to "useful stuff" mapping structure:
|
||||||
|
|
||||||
|
|
@ -157,40 +167,24 @@ namespace {
|
||||||
MVT::ValueType VT;
|
MVT::ValueType VT;
|
||||||
unsigned ldresult_ins; /// LDRESULT instruction (0 = undefined)
|
unsigned ldresult_ins; /// LDRESULT instruction (0 = undefined)
|
||||||
int prefslot_byte; /// Byte offset of the "preferred" slot
|
int prefslot_byte; /// Byte offset of the "preferred" slot
|
||||||
unsigned brcc_eq_ins; /// br_cc equal instruction
|
unsigned insmask_ins; /// Insert mask instruction for a-form
|
||||||
unsigned brcc_neq_ins; /// br_cc not equal instruction
|
|
||||||
unsigned load_aform; /// A-form load instruction for this VT
|
|
||||||
unsigned store_aform; /// A-form store instruction for this VT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const valtype_map_s valtype_map[] = {
|
const valtype_map_s valtype_map[] = {
|
||||||
{ MVT::i1, 0, 3, 0, 0, 0,
|
{ MVT::i1, 0, 3, 0 },
|
||||||
0 },
|
{ MVT::i8, SPU::ORBIr8, 3, 0 },
|
||||||
{ MVT::i8, SPU::ORBIr8, 3, 0, 0, SPU::LQAr8,
|
{ MVT::i16, SPU::ORHIr16, 2, 0 },
|
||||||
SPU::STQAr8 },
|
{ MVT::i32, SPU::ORIr32, 0, 0 },
|
||||||
{ MVT::i16, SPU::ORHIr16, 2, SPU::BRHZ, SPU::BRHNZ, SPU::LQAr16,
|
{ MVT::i64, SPU::ORIr64, 0, 0 },
|
||||||
SPU::STQAr16 },
|
{ MVT::f32, 0, 0, 0 },
|
||||||
{ MVT::i32, SPU::ORIr32, 0, SPU::BRZ, SPU::BRNZ, SPU::LQAr32,
|
{ MVT::f64, 0, 0, 0 },
|
||||||
SPU::STQAr32 },
|
|
||||||
{ MVT::i64, SPU::ORIr64, 0, 0, 0, SPU::LQAr64,
|
|
||||||
SPU::STQAr64 },
|
|
||||||
{ MVT::f32, 0, 0, 0, 0, SPU::LQAf32,
|
|
||||||
SPU::STQAf32 },
|
|
||||||
{ MVT::f64, 0, 0, 0, 0, SPU::LQAf64,
|
|
||||||
SPU::STQAf64 },
|
|
||||||
// vector types... (sigh!)
|
// vector types... (sigh!)
|
||||||
{ MVT::v16i8, 0, 0, 0, 0, SPU::LQAv16i8,
|
{ MVT::v16i8, 0, 0, SPU::CBD },
|
||||||
SPU::STQAv16i8 },
|
{ MVT::v8i16, 0, 0, SPU::CHD },
|
||||||
{ MVT::v8i16, 0, 0, 0, 0, SPU::LQAv8i16,
|
{ MVT::v4i32, 0, 0, SPU::CWD },
|
||||||
SPU::STQAv8i16 },
|
{ MVT::v2i64, 0, 0, 0 },
|
||||||
{ MVT::v4i32, 0, 0, 0, 0, SPU::LQAv4i32,
|
{ MVT::v4f32, 0, 0, SPU::CWD },
|
||||||
SPU::STQAv4i32 },
|
{ MVT::v2f64, 0, 0, 0 }
|
||||||
{ MVT::v2i64, 0, 0, 0, 0, SPU::LQAv2i64,
|
|
||||||
SPU::STQAv2i64 },
|
|
||||||
{ MVT::v4f32, 0, 0, 0, 0, SPU::LQAv4f32,
|
|
||||||
SPU::STQAv4f32 },
|
|
||||||
{ MVT::v2f64, 0, 0, 0, 0, SPU::LQAv2f64,
|
|
||||||
SPU::STQAv2f64 },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
|
const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
|
||||||
|
|
@ -381,18 +375,20 @@ SPUDAGToDAGISel::SelectDForm2Addr(SDOperand Op, SDOperand N, SDOperand &Disp,
|
||||||
Disp = CurDAG->getTargetConstant(0, VT);
|
Disp = CurDAG->getTargetConstant(0, VT);
|
||||||
Base = N;
|
Base = N;
|
||||||
return true;
|
return true;
|
||||||
} else if (Opc == SPUISD::DFormAddr) {
|
} else if (Opc == SPUISD::IndirectAddr) {
|
||||||
// D-Form address: This is pretty straightforward, naturally...
|
SDOperand Op1 = N.getOperand(1);
|
||||||
CN = cast<ConstantSDNode>(N.getOperand(1));
|
if (Op1.getOpcode() == ISD::TargetConstant
|
||||||
assert(CN != 0 && "SelectDFormAddr/SPUISD::DForm2Addr expecting constant");
|
|| Op1.getOpcode() == ISD::Constant) {
|
||||||
Imm = unsigned(CN->getValue());
|
CN = cast<ConstantSDNode>(N.getOperand(1));
|
||||||
if (Imm < 0xff) {
|
assert(CN != 0 && "SelectIndirectAddr/SPUISD::DForm2Addr expecting constant");
|
||||||
Disp = CurDAG->getTargetConstant(CN->getValue(), PtrVT);
|
Imm = unsigned(CN->getValue());
|
||||||
Base = N.getOperand(0);
|
if (Imm < 0xff) {
|
||||||
return true;
|
Disp = CurDAG->getTargetConstant(CN->getValue(), PtrVT);
|
||||||
|
Base = N.getOperand(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -407,7 +403,7 @@ SPUDAGToDAGISel::SelectAFormAddr(SDOperand Op, SDOperand N, SDOperand &Base,
|
||||||
SDOperand &Index) {
|
SDOperand &Index) {
|
||||||
// These match the addr256k operand type:
|
// These match the addr256k operand type:
|
||||||
MVT::ValueType OffsVT = MVT::i16;
|
MVT::ValueType OffsVT = MVT::i16;
|
||||||
MVT::ValueType PtrVT = SPUtli.getPointerTy();
|
SDOperand Zero = CurDAG->getTargetConstant(0, OffsVT);
|
||||||
|
|
||||||
switch (N.getOpcode()) {
|
switch (N.getOpcode()) {
|
||||||
case ISD::Constant:
|
case ISD::Constant:
|
||||||
|
|
@ -417,28 +413,40 @@ SPUDAGToDAGISel::SelectAFormAddr(SDOperand Op, SDOperand N, SDOperand &Base,
|
||||||
abort();
|
abort();
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
|
|
||||||
case ISD::TargetConstant: {
|
case ISD::TargetConstant:
|
||||||
// Loading from a constant address.
|
|
||||||
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N);
|
|
||||||
int Imm = (int)CN->getValue();
|
|
||||||
if (Imm < 0x3ffff && (Imm & 0x3) == 0) {
|
|
||||||
Base = CurDAG->getTargetConstant(Imm, PtrVT);
|
|
||||||
// Note that this operand will be ignored by the assembly printer...
|
|
||||||
Index = CurDAG->getTargetConstant(0, OffsVT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case ISD::TargetGlobalAddress:
|
case ISD::TargetGlobalAddress:
|
||||||
case ISD::TargetConstantPool:
|
case ISD::TargetJumpTable:
|
||||||
case SPUISD::AFormAddr: {
|
cerr << "SPUSelectAFormAddr: Target Constant/Pool/Global not wrapped as "
|
||||||
// The address is in Base. N is a dummy that will be ignored by
|
<< "A-form address.\n";
|
||||||
// the assembly printer.
|
abort();
|
||||||
Base = N;
|
/*NOTREACHED*/
|
||||||
Index = CurDAG->getTargetConstant(0, OffsVT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
case SPUISD::AFormAddr:
|
||||||
|
// Just load from memory if there's only a single use of the location,
|
||||||
|
// otherwise, this will get handled below with D-form offset addresses
|
||||||
|
if (N.hasOneUse()) {
|
||||||
|
SDOperand Op0 = N.getOperand(0);
|
||||||
|
switch (Op0.getOpcode()) {
|
||||||
|
case ISD::TargetConstantPool:
|
||||||
|
case ISD::TargetJumpTable:
|
||||||
|
Base = Op0;
|
||||||
|
Index = Zero;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ISD::TargetGlobalAddress: {
|
||||||
|
GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op0);
|
||||||
|
GlobalValue *GV = GSDN->getGlobal();
|
||||||
|
if (GV->getAlignment() == 16) {
|
||||||
|
Base = Op0;
|
||||||
|
Index = Zero;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -460,14 +468,11 @@ SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base,
|
||||||
unsigned Opc = N.getOpcode();
|
unsigned Opc = N.getOpcode();
|
||||||
unsigned PtrTy = SPUtli.getPointerTy();
|
unsigned PtrTy = SPUtli.getPointerTy();
|
||||||
|
|
||||||
if (Opc == ISD::Register) {
|
if (Opc == ISD::FrameIndex) {
|
||||||
Base = N;
|
// Stack frame index must be less than 512 (divided by 16):
|
||||||
Index = CurDAG->getTargetConstant(0, PtrTy);
|
|
||||||
return true;
|
|
||||||
} else if (Opc == ISD::FrameIndex) {
|
|
||||||
FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N);
|
FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N);
|
||||||
DEBUG(cerr << "SelectDFormAddr: ISD::FrameIndex = "
|
DEBUG(cerr << "SelectDFormAddr: ISD::FrameIndex = "
|
||||||
<< FI->getIndex() << "\n");
|
<< FI->getIndex() << "\n");
|
||||||
if (FI->getIndex() < SPUFrameInfo::maxFrameOffset()) {
|
if (FI->getIndex() < SPUFrameInfo::maxFrameOffset()) {
|
||||||
Base = CurDAG->getTargetConstant(0, PtrTy);
|
Base = CurDAG->getTargetConstant(0, PtrTy);
|
||||||
Index = CurDAG->getTargetFrameIndex(FI->getIndex(), PtrTy);
|
Index = CurDAG->getTargetFrameIndex(FI->getIndex(), PtrTy);
|
||||||
|
|
@ -475,19 +480,20 @@ SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base,
|
||||||
}
|
}
|
||||||
} else if (Opc == ISD::ADD) {
|
} else if (Opc == ISD::ADD) {
|
||||||
// Generated by getelementptr
|
// Generated by getelementptr
|
||||||
const SDOperand Op0 = N.getOperand(0); // Frame index/base
|
const SDOperand Op0 = N.getOperand(0);
|
||||||
const SDOperand Op1 = N.getOperand(1); // Offset within base
|
const SDOperand Op1 = N.getOperand(1);
|
||||||
|
|
||||||
if ((Op1.getOpcode() == ISD::Constant
|
if ((Op0.getOpcode() == SPUISD::Hi && Op1.getOpcode() == SPUISD::Lo)
|
||||||
|| Op1.getOpcode() == ISD::TargetConstant)
|
|| (Op1.getOpcode() == SPUISD::Hi && Op0.getOpcode() == SPUISD::Lo)) {
|
||||||
&& Op0.getOpcode() != SPUISD::XFormAddr) {
|
Base = CurDAG->getTargetConstant(0, PtrTy);
|
||||||
|
Index = N;
|
||||||
|
return true;
|
||||||
|
} else if (Op1.getOpcode() == ISD::Constant
|
||||||
|
|| Op1.getOpcode() == ISD::TargetConstant) {
|
||||||
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1);
|
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1);
|
||||||
assert(CN != 0 && "SelectDFormAddr: Expected a constant");
|
int32_t offset = int32_t(CN->getSignExtended());
|
||||||
|
|
||||||
int32_t offset = (int32_t) CN->getSignExtended();
|
if (Op0.getOpcode() == ISD::FrameIndex) {
|
||||||
unsigned Opc0 = Op0.getOpcode();
|
|
||||||
|
|
||||||
if (Opc0 == ISD::FrameIndex) {
|
|
||||||
FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op0);
|
FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op0);
|
||||||
DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset
|
DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset
|
||||||
<< " frame index = " << FI->getIndex() << "\n");
|
<< " frame index = " << FI->getIndex() << "\n");
|
||||||
|
|
@ -500,51 +506,69 @@ SPUDAGToDAGISel::SelectDFormAddr(SDOperand Op, SDOperand N, SDOperand &Base,
|
||||||
} else if (offset > SPUFrameInfo::minFrameOffset()
|
} else if (offset > SPUFrameInfo::minFrameOffset()
|
||||||
&& offset < SPUFrameInfo::maxFrameOffset()) {
|
&& offset < SPUFrameInfo::maxFrameOffset()) {
|
||||||
Base = CurDAG->getTargetConstant(offset, PtrTy);
|
Base = CurDAG->getTargetConstant(offset, PtrTy);
|
||||||
if (Opc0 == ISD::GlobalAddress) {
|
Index = Op0;
|
||||||
// Convert global address to target global address
|
return true;
|
||||||
GlobalAddressSDNode *GV = dyn_cast<GlobalAddressSDNode>(Op0);
|
}
|
||||||
Index = CurDAG->getTargetGlobalAddress(GV->getGlobal(), PtrTy);
|
} else if (Op0.getOpcode() == ISD::Constant
|
||||||
return true;
|
|| Op0.getOpcode() == ISD::TargetConstant) {
|
||||||
} else {
|
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op0);
|
||||||
// Otherwise, just take operand 0
|
int32_t offset = int32_t(CN->getSignExtended());
|
||||||
Index = Op0;
|
|
||||||
|
if (Op1.getOpcode() == ISD::FrameIndex) {
|
||||||
|
FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op1);
|
||||||
|
DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset
|
||||||
|
<< " frame index = " << FI->getIndex() << "\n");
|
||||||
|
|
||||||
|
if (FI->getIndex() < SPUFrameInfo::maxFrameOffset()) {
|
||||||
|
Base = CurDAG->getTargetConstant(offset, PtrTy);
|
||||||
|
Index = CurDAG->getTargetFrameIndex(FI->getIndex(), PtrTy);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} else if (offset > SPUFrameInfo::minFrameOffset()
|
||||||
|
&& offset < SPUFrameInfo::maxFrameOffset()) {
|
||||||
|
Base = CurDAG->getTargetConstant(offset, PtrTy);
|
||||||
|
Index = Op1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
return false;
|
} else if (Opc == SPUISD::IndirectAddr) {
|
||||||
} else if (Opc == SPUISD::DFormAddr) {
|
// Indirect with constant offset -> D-Form address
|
||||||
// D-Form address: This is pretty straightforward,
|
const SDOperand Op0 = N.getOperand(0);
|
||||||
// naturally... but make sure that this isn't a D-form address
|
const SDOperand Op1 = N.getOperand(1);
|
||||||
// with a X-form address embedded within:
|
SDOperand Zero = CurDAG->getTargetConstant(0, N.getValueType());
|
||||||
const SDOperand Op0 = N.getOperand(0); // Frame index/base
|
|
||||||
const SDOperand Op1 = N.getOperand(1); // Offset within base
|
|
||||||
|
|
||||||
if (Op0.getOpcode() == ISD::Constant
|
if (Op1.getOpcode() == ISD::Constant
|
||||||
|| Op0.getOpcode() == ISD::TargetConstant) {
|
|| Op1.getOpcode() == ISD::TargetConstant) {
|
||||||
ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
|
ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
|
||||||
assert(CN != 0 && "SelectDFormAddr/SPUISD::DFormAddr expecting constant");
|
int32_t offset = int32_t(CN->getSignExtended());
|
||||||
Base = CurDAG->getTargetConstant(CN->getValue(), PtrTy);
|
if (offset > SPUFrameInfo::minFrameOffset()
|
||||||
Index = Op0;
|
&& offset < SPUFrameInfo::maxFrameOffset()) {
|
||||||
return true;
|
Base = CurDAG->getTargetConstant(CN->getValue(), PtrTy);
|
||||||
}
|
Index = Op0;
|
||||||
} else if (Opc == ISD::FrameIndex) {
|
return true;
|
||||||
// Stack frame index must be less than 512 (divided by 16):
|
}
|
||||||
FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N);
|
} else if (Op0.getOpcode() == ISD::Constant
|
||||||
DEBUG(cerr << "SelectDFormAddr: ISD::FrameIndex = "
|
|| Op0.getOpcode() == ISD::TargetConstant) {
|
||||||
<< FI->getIndex() << "\n");
|
ConstantSDNode *CN = cast<ConstantSDNode>(Op0);
|
||||||
if (FI->getIndex() < SPUFrameInfo::maxFrameOffset()) {
|
int32_t offset = int32_t(CN->getSignExtended());
|
||||||
|
if (offset > SPUFrameInfo::minFrameOffset()
|
||||||
|
&& offset < SPUFrameInfo::maxFrameOffset()) {
|
||||||
|
Base = CurDAG->getTargetConstant(CN->getValue(), PtrTy);
|
||||||
|
Index = Op1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (Op0.getOpcode() == SPUISD::Hi
|
||||||
|
&& Op1.getOpcode() == SPUISD::Lo) {
|
||||||
|
// (SPUindirect (SPUhi <arg>, 0), (SPUlo <arg>, 0))
|
||||||
Base = CurDAG->getTargetConstant(0, PtrTy);
|
Base = CurDAG->getTargetConstant(0, PtrTy);
|
||||||
Index = CurDAG->getTargetFrameIndex(FI->getIndex(), PtrTy);
|
Index = N;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (Opc == SPUISD::LDRESULT) {
|
} else if (Opc == SPUISD::AFormAddr) {
|
||||||
// It's a load result dereference
|
Base = CurDAG->getTargetConstant(0, N.getValueType());
|
||||||
Base = CurDAG->getTargetConstant(0, PtrTy);
|
Index = N;
|
||||||
Index = N.getOperand(0);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -565,108 +589,10 @@ SPUDAGToDAGISel::SelectXFormAddr(SDOperand Op, SDOperand N, SDOperand &Base,
|
||||||
|| SelectDFormAddr(Op, N, Base, Index))
|
|| SelectDFormAddr(Op, N, Base, Index))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned Opc = N.getOpcode();
|
// All else fails, punt and use an X-form address:
|
||||||
|
Base = N.getOperand(0);
|
||||||
if (Opc == ISD::ADD) {
|
Index = N.getOperand(1);
|
||||||
SDOperand N1 = N.getOperand(0);
|
return true;
|
||||||
SDOperand N2 = N.getOperand(1);
|
|
||||||
Base = N.getOperand(0);
|
|
||||||
Index = N.getOperand(1);
|
|
||||||
return true;
|
|
||||||
} else if (Opc == SPUISD::XFormAddr) {
|
|
||||||
Base = N;
|
|
||||||
Index = N.getOperand(1);
|
|
||||||
return true;
|
|
||||||
} else if (Opc == SPUISD::DFormAddr) {
|
|
||||||
// Must be a D-form address with an X-form address embedded
|
|
||||||
// within:
|
|
||||||
Base = N.getOperand(0);
|
|
||||||
Index = N.getOperand(1);
|
|
||||||
return true;
|
|
||||||
} else if (N.getNumOperands() == 2) {
|
|
||||||
SDOperand N1 = N.getOperand(0);
|
|
||||||
SDOperand N2 = N.getOperand(1);
|
|
||||||
unsigned N1Opc = N1.getOpcode();
|
|
||||||
unsigned N2Opc = N2.getOpcode();
|
|
||||||
|
|
||||||
if ((N1Opc == ISD::CopyToReg || N1Opc == ISD::Register)
|
|
||||||
&& (N2Opc == ISD::CopyToReg || N2Opc == ISD::Register)) {
|
|
||||||
Base = N.getOperand(0);
|
|
||||||
Index = N.getOperand(1);
|
|
||||||
return true;
|
|
||||||
/*UNREACHED*/
|
|
||||||
} else {
|
|
||||||
cerr << "SelectXFormAddr: 2-operand unhandled operand:\n";
|
|
||||||
N.Val->dump(CurDAG);
|
|
||||||
cerr << "\n";
|
|
||||||
abort();
|
|
||||||
/*UNREACHED*/
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cerr << "SelectXFormAddr: Unhandled operand type:\n";
|
|
||||||
N.Val->dump(CurDAG);
|
|
||||||
cerr << "\n";
|
|
||||||
abort();
|
|
||||||
/*UNREACHED*/
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Emit load for A-form addresses
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
SDNode *
|
|
||||||
Emit_LOAD_AFormAddr(SDOperand Op, SelectionDAG &CurDAG, SPUDAGToDAGISel &ISel)
|
|
||||||
{
|
|
||||||
SDNode *Result;
|
|
||||||
MVT::ValueType OpVT = Op.getValueType();
|
|
||||||
SDOperand Chain = Op.getOperand(0);
|
|
||||||
SDOperand Ptr = Op.getOperand(1);
|
|
||||||
SDOperand PtrArg = Ptr.getOperand(0);
|
|
||||||
SDOperand PtrOffs = Ptr.getOperand(1);
|
|
||||||
const valtype_map_s *vtm = getValueTypeMapEntry(OpVT);
|
|
||||||
|
|
||||||
if (PtrOffs.getOpcode() == ISD::Constant) {
|
|
||||||
ConstantSDNode *CN = cast<ConstantSDNode>(PtrOffs);
|
|
||||||
MVT::ValueType PVT = PtrOffs.getValueType();
|
|
||||||
PtrOffs = CurDAG.getTargetConstant(CN->getValue(), PVT);
|
|
||||||
}
|
|
||||||
ISel.AddToISelQueue(PtrArg);
|
|
||||||
ISel.AddToISelQueue(PtrOffs);
|
|
||||||
ISel.AddToISelQueue(Chain);
|
|
||||||
Result = CurDAG.getTargetNode(vtm->load_aform, OpVT, MVT::Other, PtrArg, PtrOffs, Chain);
|
|
||||||
Chain = SDOperand(Result, 1);
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Emit store for A-form addresses
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
SDNode *
|
|
||||||
Emit_STORE_AFormAddr(SDOperand Op, SelectionDAG &CurDAG, SPUDAGToDAGISel &ISel)
|
|
||||||
{
|
|
||||||
SDNode *Result;
|
|
||||||
SDOperand Chain = Op.getOperand(0);
|
|
||||||
SDOperand Val = Op.getOperand(1);
|
|
||||||
SDOperand Ptr = Op.getOperand(2);
|
|
||||||
SDOperand PtrArg = Ptr.getOperand(0);
|
|
||||||
SDOperand PtrOffs = Ptr.getOperand(1);
|
|
||||||
const valtype_map_s *vtm = getValueTypeMapEntry(Val.getValueType());
|
|
||||||
|
|
||||||
if (PtrOffs.getOpcode() == ISD::Constant) {
|
|
||||||
ConstantSDNode *CN = cast<ConstantSDNode>(PtrOffs);
|
|
||||||
MVT::ValueType PVT = PtrOffs.getValueType();
|
|
||||||
PtrOffs = CurDAG.getTargetConstant(CN->getValue(), PVT);
|
|
||||||
}
|
|
||||||
ISel.AddToISelQueue(Val);
|
|
||||||
ISel.AddToISelQueue(PtrArg);
|
|
||||||
ISel.AddToISelQueue(PtrOffs);
|
|
||||||
ISel.AddToISelQueue(Chain);
|
|
||||||
SDOperand Ops[4] = { Val, PtrArg, PtrOffs, Chain };
|
|
||||||
Result = CurDAG.getTargetNode(vtm->store_aform, MVT::Other, Ops, 4);
|
|
||||||
Chain = SDOperand(Result, 1);
|
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Convert the operand from a target-independent to a target-specific node
|
//! Convert the operand from a target-independent to a target-specific node
|
||||||
|
|
@ -695,12 +621,6 @@ SPUDAGToDAGISel::Select(SDOperand Op) {
|
||||||
Ops[0] = TFI;
|
Ops[0] = TFI;
|
||||||
Ops[1] = Zero;
|
Ops[1] = Zero;
|
||||||
n_ops = 2;
|
n_ops = 2;
|
||||||
} else if (Opc == ISD::LOAD
|
|
||||||
&& Op.getOperand(1).getOpcode() == SPUISD::AFormAddr) {
|
|
||||||
return Emit_LOAD_AFormAddr(Op, *CurDAG, *this);
|
|
||||||
} else if (Opc == ISD::STORE
|
|
||||||
&& Op.getOperand(2).getOpcode() == SPUISD::AFormAddr) {
|
|
||||||
return Emit_STORE_AFormAddr(Op, *CurDAG, *this);
|
|
||||||
} else if (Opc == ISD::ZERO_EXTEND) {
|
} else if (Opc == ISD::ZERO_EXTEND) {
|
||||||
// (zero_extend:i16 (and:i8 <arg>, <const>))
|
// (zero_extend:i16 (and:i8 <arg>, <const>))
|
||||||
const SDOperand &Op1 = N->getOperand(0);
|
const SDOperand &Op1 = N->getOperand(0);
|
||||||
|
|
@ -717,6 +637,38 @@ SPUDAGToDAGISel::Select(SDOperand Op) {
|
||||||
n_ops = 2;
|
n_ops = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (Opc == SPUISD::INSERT_MASK) {
|
||||||
|
SDOperand Op0 = Op.getOperand(0);
|
||||||
|
if (Op0.getOpcode() == SPUISD::AFormAddr) {
|
||||||
|
// (SPUvecinsmask (SPUaform <arg>, 0)) ->
|
||||||
|
// (CBD|CHD|CWD 0, arg)
|
||||||
|
const valtype_map_s *vtm = getValueTypeMapEntry(OpVT);
|
||||||
|
ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getOperand(1));
|
||||||
|
assert(vtm->insmask_ins != 0 && "missing insert mask instruction");
|
||||||
|
NewOpc = vtm->insmask_ins;
|
||||||
|
Ops[0] = CurDAG->getTargetConstant(CN->getValue(), Op0.getValueType());
|
||||||
|
Ops[1] = Op0;
|
||||||
|
n_ops = 2;
|
||||||
|
|
||||||
|
AddToISelQueue(Op0);
|
||||||
|
} else if (Op0.getOpcode() == ISD::FrameIndex) {
|
||||||
|
// (SPUvecinsmask <fi>) ->
|
||||||
|
// (CBD|CHD|CWD 0, <fi>)
|
||||||
|
const valtype_map_s *vtm = getValueTypeMapEntry(OpVT);
|
||||||
|
NewOpc = vtm->insmask_ins;
|
||||||
|
Ops[0] = CurDAG->getTargetConstant(0, Op0.getValueType());
|
||||||
|
Ops[1] = Op0;
|
||||||
|
n_ops = 2;
|
||||||
|
} else if (isHighLow(Op0)) {
|
||||||
|
// (SPUvecinsmask (SPUindirect (SPUhi <arg>, 0), (SPUlow <arg>, 0))) ->
|
||||||
|
// (CBD|CHD|CWD 0, arg)
|
||||||
|
const valtype_map_s *vtm = getValueTypeMapEntry(OpVT);
|
||||||
|
NewOpc = vtm->insmask_ins;
|
||||||
|
Ops[0] = CurDAG->getTargetConstant(0, Op0.getValueType());
|
||||||
|
Ops[1] = Op0;
|
||||||
|
n_ops = 2;
|
||||||
|
AddToISelQueue(Op0);
|
||||||
|
}
|
||||||
} else if (Opc == SPUISD::LDRESULT) {
|
} else if (Opc == SPUISD::LDRESULT) {
|
||||||
// Custom select instructions for LDRESULT
|
// Custom select instructions for LDRESULT
|
||||||
unsigned VT = N->getValueType(0);
|
unsigned VT = N->getValueType(0);
|
||||||
|
|
@ -748,19 +700,19 @@ SPUDAGToDAGISel::Select(SDOperand Op) {
|
||||||
AddToISelQueue(Chain);
|
AddToISelQueue(Chain);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
} else if (Opc == SPUISD::XFormAddr) {
|
} else if (Opc == SPUISD::IndirectAddr) {
|
||||||
SDOperand Op0 = Op.getOperand(0);
|
SDOperand Op0 = Op.getOperand(0);
|
||||||
if (Op0.getOpcode() == SPUISD::LDRESULT
|
if (Op0.getOpcode() == SPUISD::LDRESULT
|
||||||
|| Op0.getOpcode() == SPUISD::AFormAddr) {
|
|| Op0.getOpcode() == SPUISD::AFormAddr) {
|
||||||
// (XFormAddr (LDRESULT|AFormAddr, imm))
|
// (IndirectAddr (LDRESULT|AFormAddr, imm))
|
||||||
SDOperand Op1 = Op.getOperand(1);
|
SDOperand Op1 = Op.getOperand(1);
|
||||||
MVT::ValueType VT = Op.getValueType();
|
MVT::ValueType VT = Op.getValueType();
|
||||||
|
|
||||||
DEBUG(cerr << "CellSPU: XFormAddr("
|
DEBUG(cerr << "CellSPU: IndirectAddr("
|
||||||
<< (Op0.getOpcode() == SPUISD::LDRESULT
|
<< (Op0.getOpcode() == SPUISD::LDRESULT
|
||||||
? "LDRESULT"
|
? "LDRESULT"
|
||||||
: "AFormAddr")
|
: "AFormAddr")
|
||||||
<< ", imm):\nOp0 = ");
|
<< ", imm):\nOp0 = ");
|
||||||
DEBUG(Op.getOperand(0).Val->dump(CurDAG));
|
DEBUG(Op.getOperand(0).Val->dump(CurDAG));
|
||||||
DEBUG(cerr << "\nOp1 = ");
|
DEBUG(cerr << "\nOp1 = ");
|
||||||
DEBUG(Op.getOperand(1).Val->dump(CurDAG));
|
DEBUG(Op.getOperand(1).Val->dump(CurDAG));
|
||||||
|
|
|
||||||
|
|
@ -289,14 +289,12 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
|
||||||
|
|
||||||
// We want to legalize GlobalAddress and ConstantPool nodes into the
|
// We want to legalize GlobalAddress and ConstantPool nodes into the
|
||||||
// appropriate instructions to materialize the address.
|
// appropriate instructions to materialize the address.
|
||||||
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
|
for (unsigned sctype = (unsigned) MVT::i1; sctype < (unsigned) MVT::f128;
|
||||||
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
|
++sctype) {
|
||||||
setOperationAction(ISD::ConstantPool, MVT::f32, Custom);
|
setOperationAction(ISD::GlobalAddress, sctype, Custom);
|
||||||
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
|
setOperationAction(ISD::ConstantPool, sctype, Custom);
|
||||||
setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
|
setOperationAction(ISD::JumpTable, sctype, Custom);
|
||||||
setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
|
}
|
||||||
setOperationAction(ISD::ConstantPool, MVT::f64, Custom);
|
|
||||||
setOperationAction(ISD::JumpTable, MVT::i64, Custom);
|
|
||||||
|
|
||||||
// RET must be custom lowered, to meet ABI requirements
|
// RET must be custom lowered, to meet ABI requirements
|
||||||
setOperationAction(ISD::RET, MVT::Other, Custom);
|
setOperationAction(ISD::RET, MVT::Other, Custom);
|
||||||
|
|
@ -377,7 +375,7 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
|
||||||
setStackPointerRegisterToSaveRestore(SPU::R1);
|
setStackPointerRegisterToSaveRestore(SPU::R1);
|
||||||
|
|
||||||
// We have target-specific dag combine patterns for the following nodes:
|
// We have target-specific dag combine patterns for the following nodes:
|
||||||
// e.g., setTargetDAGCombine(ISD::SUB);
|
setTargetDAGCombine(ISD::ADD);
|
||||||
|
|
||||||
computeRegisterProperties();
|
computeRegisterProperties();
|
||||||
}
|
}
|
||||||
|
|
@ -391,8 +389,7 @@ SPUTargetLowering::getTargetNodeName(unsigned Opcode) const
|
||||||
node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
|
node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
|
||||||
node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
|
node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
|
||||||
node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
|
node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
|
||||||
node_names[(unsigned) SPUISD::DFormAddr] = "SPUISD::DFormAddr";
|
node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
|
||||||
node_names[(unsigned) SPUISD::XFormAddr] = "SPUISD::XFormAddr";
|
|
||||||
node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
|
node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
|
||||||
node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
|
node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
|
||||||
node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
|
node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
|
||||||
|
|
@ -524,11 +521,12 @@ AlignedLoad(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST,
|
||||||
// Unaligned load or we're using the "large memory" model, which means that
|
// Unaligned load or we're using the "large memory" model, which means that
|
||||||
// we have to be very pessimistic:
|
// we have to be very pessimistic:
|
||||||
if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
|
if (isMemoryOperand(basePtr) || isIndirectOperand(basePtr)) {
|
||||||
basePtr = DAG.getNode(SPUISD::XFormAddr, PtrVT, basePtr, DAG.getConstant(0, PtrVT));
|
basePtr = DAG.getNode(SPUISD::IndirectAddr, PtrVT, basePtr, DAG.getConstant(0, PtrVT));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the offset
|
// Add the offset
|
||||||
basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, DAG.getConstant(alignOffs, PtrVT));
|
basePtr = DAG.getNode(ISD::ADD, PtrVT, basePtr,
|
||||||
|
DAG.getConstant((alignOffs & ~0xf), PtrVT));
|
||||||
was16aligned = false;
|
was16aligned = false;
|
||||||
return DAG.getLoad(MVT::v16i8, chain, basePtr,
|
return DAG.getLoad(MVT::v16i8, chain, basePtr,
|
||||||
LSN->getSrcValue(), LSN->getSrcValueOffset(),
|
LSN->getSrcValue(), LSN->getSrcValueOffset(),
|
||||||
|
|
@ -706,21 +704,20 @@ LowerSTORE(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
|
||||||
DEBUG(basePtr.Val->dump(&DAG));
|
DEBUG(basePtr.Val->dump(&DAG));
|
||||||
DEBUG(cerr << "\n");
|
DEBUG(cerr << "\n");
|
||||||
|
|
||||||
if (basePtr.getOpcode() == SPUISD::DFormAddr) {
|
if (basePtr.getOpcode() == SPUISD::IndirectAddr ||
|
||||||
// Hmmmm... do we ever actually hit this code?
|
(basePtr.getOpcode() == ISD::ADD
|
||||||
insertEltPtr = DAG.getNode(SPUISD::DFormAddr, PtrVT,
|
&& basePtr.getOperand(0).getOpcode() == SPUISD::IndirectAddr)) {
|
||||||
basePtr.getOperand(0),
|
|
||||||
insertEltOffs);
|
|
||||||
} else if (basePtr.getOpcode() == SPUISD::XFormAddr ||
|
|
||||||
(basePtr.getOpcode() == ISD::ADD
|
|
||||||
&& basePtr.getOperand(0).getOpcode() == SPUISD::XFormAddr)) {
|
|
||||||
insertEltPtr = basePtr;
|
insertEltPtr = basePtr;
|
||||||
} else {
|
} else {
|
||||||
// $sp is always aligned, so use it instead of potentially loading an
|
#if 0
|
||||||
// address into a new register:
|
// $sp is always aligned, so use it when necessary to avoid loading
|
||||||
insertEltPtr = DAG.getNode(SPUISD::DFormAddr, PtrVT,
|
// an address
|
||||||
DAG.getRegister(SPU::R1, PtrVT),
|
SDOperand ptrP =
|
||||||
insertEltOffs);
|
basePtr.Val->hasOneUse() ? DAG.getRegister(SPU::R1, PtrVT) : basePtr;
|
||||||
|
insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, ptrP, insertEltOffs);
|
||||||
|
#else
|
||||||
|
insertEltPtr = DAG.getNode(ISD::ADD, PtrVT, basePtr, insertEltOffs);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
insertEltOp = DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
|
insertEltOp = DAG.getNode(SPUISD::INSERT_MASK, stVecVT, insertEltPtr);
|
||||||
|
|
@ -772,7 +769,7 @@ LowerConstantPool(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
|
||||||
|
|
||||||
return DAG.getNode(ISD::ADD, PtrVT, Lo, Hi);
|
return DAG.getNode(ISD::ADD, PtrVT, Lo, Hi);
|
||||||
#else
|
#else
|
||||||
return DAG.getNode(SPUISD::XFormAddr, PtrVT, CPI, Zero);
|
return DAG.getNode(SPUISD::IndirectAddr, PtrVT, CPI, Zero);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -791,9 +788,10 @@ LowerJumpTable(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
|
||||||
const TargetMachine &TM = DAG.getTarget();
|
const TargetMachine &TM = DAG.getTarget();
|
||||||
|
|
||||||
if (TM.getRelocationModel() == Reloc::Static) {
|
if (TM.getRelocationModel() == Reloc::Static) {
|
||||||
|
SDOperand JmpAForm = DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero);
|
||||||
return (!ST->usingLargeMem()
|
return (!ST->usingLargeMem()
|
||||||
? DAG.getNode(SPUISD::AFormAddr, PtrVT, JTI, Zero)
|
? JmpAForm
|
||||||
: DAG.getNode(SPUISD::XFormAddr, PtrVT, JTI, Zero));
|
: DAG.getNode(SPUISD::IndirectAddr, PtrVT, JmpAForm, Zero));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(0 &&
|
assert(0 &&
|
||||||
|
|
@ -811,9 +809,13 @@ LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
|
||||||
SDOperand Zero = DAG.getConstant(0, PtrVT);
|
SDOperand Zero = DAG.getConstant(0, PtrVT);
|
||||||
|
|
||||||
if (TM.getRelocationModel() == Reloc::Static) {
|
if (TM.getRelocationModel() == Reloc::Static) {
|
||||||
return (!ST->usingLargeMem()
|
if (!ST->usingLargeMem()) {
|
||||||
? DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero)
|
return DAG.getNode(SPUISD::AFormAddr, PtrVT, GA, Zero);
|
||||||
: DAG.getNode(SPUISD::XFormAddr, PtrVT, GA, Zero));
|
} else {
|
||||||
|
SDOperand Hi = DAG.getNode(SPUISD::Hi, PtrVT, GA, Zero);
|
||||||
|
SDOperand Lo = DAG.getNode(SPUISD::Lo, PtrVT, GA, Zero);
|
||||||
|
return DAG.getNode(SPUISD::IndirectAddr, PtrVT, Hi, Lo);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cerr << "LowerGlobalAddress: Relocation model other than static not "
|
cerr << "LowerGlobalAddress: Relocation model other than static not "
|
||||||
<< "supported.\n";
|
<< "supported.\n";
|
||||||
|
|
@ -1202,7 +1204,7 @@ LowerCALL(SDOperand Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
|
||||||
} else {
|
} else {
|
||||||
// "Large memory" mode: Turn all calls into indirect calls with a X-form
|
// "Large memory" mode: Turn all calls into indirect calls with a X-form
|
||||||
// address pairs:
|
// address pairs:
|
||||||
Callee = DAG.getNode(SPUISD::XFormAddr, PtrVT, GA, Zero);
|
Callee = DAG.getNode(SPUISD::IndirectAddr, PtrVT, GA, Zero);
|
||||||
}
|
}
|
||||||
} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
|
} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
|
||||||
Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
|
Callee = DAG.getExternalSymbol(S->getSymbol(), Callee.getValueType());
|
||||||
|
|
@ -2553,16 +2555,80 @@ SPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
TargetMachine &TM = getTargetMachine();
|
TargetMachine &TM = getTargetMachine();
|
||||||
|
#endif
|
||||||
|
const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
|
||||||
SelectionDAG &DAG = DCI.DAG;
|
SelectionDAG &DAG = DCI.DAG;
|
||||||
SDOperand N0 = N->getOperand(0); // everything has at least one operand
|
SDOperand N0 = N->getOperand(0); // everything has at least one operand
|
||||||
|
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default: break;
|
default: break;
|
||||||
// Do something creative here for ISD nodes that can be coalesced in unique
|
case SPUISD::IndirectAddr: {
|
||||||
// ways.
|
if (!ST->usingLargeMem() && N0.getOpcode() == SPUISD::AFormAddr) {
|
||||||
|
ConstantSDNode *CN = cast<ConstantSDNode>(N->getOperand(1));
|
||||||
|
if (CN->getValue() == 0) {
|
||||||
|
// (SPUindirect (SPUaform <addr>, 0), 0) ->
|
||||||
|
// (SPUaform <addr>, 0)
|
||||||
|
|
||||||
|
DEBUG(cerr << "Replace: ");
|
||||||
|
DEBUG(N->dump(&DAG));
|
||||||
|
DEBUG(cerr << "\nWith: ");
|
||||||
|
DEBUG(N0.Val->dump(&DAG));
|
||||||
|
DEBUG(cerr << "\n");
|
||||||
|
|
||||||
|
return N0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case ISD::ADD: {
|
||||||
|
SDOperand Op0 = N->getOperand(0);
|
||||||
|
SDOperand Op1 = N->getOperand(1);
|
||||||
|
|
||||||
|
if ((Op1.getOpcode() == ISD::Constant
|
||||||
|
|| Op1.getOpcode() == ISD::TargetConstant)
|
||||||
|
&& Op0.getOpcode() == SPUISD::IndirectAddr) {
|
||||||
|
SDOperand Op01 = Op0.getOperand(1);
|
||||||
|
if (Op01.getOpcode() == ISD::Constant
|
||||||
|
|| Op01.getOpcode() == ISD::TargetConstant) {
|
||||||
|
// (add <const>, (SPUindirect <arg>, <const>)) ->
|
||||||
|
// (SPUindirect <arg>, <const + const>)
|
||||||
|
ConstantSDNode *CN0 = cast<ConstantSDNode>(Op1);
|
||||||
|
ConstantSDNode *CN1 = cast<ConstantSDNode>(Op01);
|
||||||
|
SDOperand combinedConst =
|
||||||
|
DAG.getConstant(CN0->getValue() + CN1->getValue(),
|
||||||
|
Op0.getValueType());
|
||||||
|
|
||||||
|
DEBUG(cerr << "Replace: (add " << CN0->getValue() << ", "
|
||||||
|
<< "(SPUindirect <arg>, " << CN1->getValue() << "))\n");
|
||||||
|
DEBUG(cerr << "With: (SPUindirect <arg>, "
|
||||||
|
<< CN0->getValue() + CN1->getValue() << ")\n");
|
||||||
|
return DAG.getNode(SPUISD::IndirectAddr, Op0.getValueType(),
|
||||||
|
Op0.getOperand(0), combinedConst);
|
||||||
|
}
|
||||||
|
} else if ((Op0.getOpcode() == ISD::Constant
|
||||||
|
|| Op0.getOpcode() == ISD::TargetConstant)
|
||||||
|
&& Op1.getOpcode() == SPUISD::IndirectAddr) {
|
||||||
|
SDOperand Op11 = Op1.getOperand(1);
|
||||||
|
if (Op11.getOpcode() == ISD::Constant
|
||||||
|
|| Op11.getOpcode() == ISD::TargetConstant) {
|
||||||
|
// (add (SPUindirect <arg>, <const>), <const>) ->
|
||||||
|
// (SPUindirect <arg>, <const + const>)
|
||||||
|
ConstantSDNode *CN0 = cast<ConstantSDNode>(Op0);
|
||||||
|
ConstantSDNode *CN1 = cast<ConstantSDNode>(Op11);
|
||||||
|
SDOperand combinedConst =
|
||||||
|
DAG.getConstant(CN0->getValue() + CN1->getValue(),
|
||||||
|
Op0.getValueType());
|
||||||
|
|
||||||
|
DEBUG(cerr << "Replace: (add " << CN0->getValue() << ", "
|
||||||
|
<< "(SPUindirect <arg>, " << CN1->getValue() << "))\n");
|
||||||
|
DEBUG(cerr << "With: (SPUindirect <arg>, "
|
||||||
|
<< CN0->getValue() + CN1->getValue() << ")\n");
|
||||||
|
|
||||||
|
return DAG.getNode(SPUISD::IndirectAddr, Op1.getValueType(),
|
||||||
|
Op1.getOperand(0), combinedConst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Otherwise, return unchanged.
|
// Otherwise, return unchanged.
|
||||||
return SDOperand();
|
return SDOperand();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,7 @@ namespace llvm {
|
||||||
Lo, ///< Low address component (lower 16)
|
Lo, ///< Low address component (lower 16)
|
||||||
PCRelAddr, ///< Program counter relative address
|
PCRelAddr, ///< Program counter relative address
|
||||||
AFormAddr, ///< A-form address (local store)
|
AFormAddr, ///< A-form address (local store)
|
||||||
DFormAddr, ///< D-Form address "imm($r)"
|
IndirectAddr, ///< D-Form "imm($r)" and X-form "$r($r)"
|
||||||
XFormAddr, ///< X-Form address "$r($r)"
|
|
||||||
|
|
||||||
LDRESULT, ///< Load result (value, chain)
|
LDRESULT, ///< Load result (value, chain)
|
||||||
CALL, ///< CALL instruction
|
CALL, ///< CALL instruction
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,10 @@ let RT = 0 in {
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Specialized versions of RI16:
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// RI18 Format
|
// RI18 Format
|
||||||
class RI18Form<bits<7> opcode, dag OOL, dag IOL, string asmstr,
|
class RI18Form<bits<7> opcode, dag OOL, dag IOL, string asmstr,
|
||||||
InstrItinClass itin, list<dag> pattern>
|
InstrItinClass itin, list<dag> pattern>
|
||||||
|
|
|
||||||
|
|
@ -48,205 +48,109 @@ def DWARF_LOC : Pseudo<(outs), (ins i32imm:$line, i32imm:$col, i32imm:$fi
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
let isSimpleLoad = 1 in {
|
let isSimpleLoad = 1 in {
|
||||||
def LQDv16i8:
|
class LoadDFormVec<ValueType vectype>
|
||||||
RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
|
: RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
|
||||||
"lqd\t$rT, $src", LoadStore,
|
"lqd\t$rT, $src",
|
||||||
[(set (v16i8 VECREG:$rT), (load dform_addr:$src))]>;
|
LoadStore,
|
||||||
|
[(set (vectype VECREG:$rT), (load dform_addr:$src))]>
|
||||||
|
{ }
|
||||||
|
|
||||||
def LQDv8i16:
|
class LoadDForm<RegisterClass rclass>
|
||||||
RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
|
: RI10Form<0b00101100, (outs rclass:$rT), (ins memri10:$src),
|
||||||
"lqd\t$rT, $src", LoadStore,
|
"lqd\t$rT, $src",
|
||||||
[(set (v8i16 VECREG:$rT), (load dform_addr:$src))]>;
|
LoadStore,
|
||||||
|
[(set rclass:$rT, (load dform_addr:$src))]>
|
||||||
|
{ }
|
||||||
|
|
||||||
def LQDv4i32:
|
multiclass LoadDForms
|
||||||
RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
|
{
|
||||||
"lqd\t$rT, $src", LoadStore,
|
def v16i8: LoadDFormVec<v16i8>;
|
||||||
[(set (v4i32 VECREG:$rT), (load dform_addr:$src))]>;
|
def v8i16: LoadDFormVec<v8i16>;
|
||||||
|
def v4i32: LoadDFormVec<v4i32>;
|
||||||
|
def v2i64: LoadDFormVec<v2i64>;
|
||||||
|
def v4f32: LoadDFormVec<v4f32>;
|
||||||
|
def v2f64: LoadDFormVec<v2f64>;
|
||||||
|
|
||||||
def LQDv2i64:
|
def r128: LoadDForm<GPRC>;
|
||||||
RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
|
def r64: LoadDForm<R64C>;
|
||||||
"lqd\t$rT, $src", LoadStore,
|
def r32: LoadDForm<R32C>;
|
||||||
[(set (v2i64 VECREG:$rT), (load dform_addr:$src))]>;
|
def f32: LoadDForm<R32FP>;
|
||||||
|
def f64: LoadDForm<R64FP>;
|
||||||
|
def r16: LoadDForm<R16C>;
|
||||||
|
def r8: LoadDForm<R8C>;
|
||||||
|
}
|
||||||
|
|
||||||
def LQDv4f32:
|
class LoadAFormVec<ValueType vectype>
|
||||||
RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
|
: RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
|
||||||
"lqd\t$rT, $src", LoadStore,
|
"lqa\t$rT, $src",
|
||||||
[(set (v4f32 VECREG:$rT), (load dform_addr:$src))]>;
|
LoadStore,
|
||||||
|
[(set (vectype VECREG:$rT), (load aform_addr:$src))]>
|
||||||
|
{ }
|
||||||
|
|
||||||
def LQDv2f64:
|
class LoadAForm<RegisterClass rclass>
|
||||||
RI10Form<0b00101100, (outs VECREG:$rT), (ins memri10:$src),
|
: RI16Form<0b100001100, (outs rclass:$rT), (ins addr256k:$src),
|
||||||
"lqd\t$rT, $src", LoadStore,
|
"lqa\t$rT, $src",
|
||||||
[(set (v2f64 VECREG:$rT), (load dform_addr:$src))]>;
|
LoadStore,
|
||||||
|
[(set rclass:$rT, (load aform_addr:$src))]>
|
||||||
|
{ }
|
||||||
|
|
||||||
def LQDr128:
|
multiclass LoadAForms
|
||||||
RI10Form<0b00101100, (outs GPRC:$rT), (ins memri10:$src),
|
{
|
||||||
"lqd\t$rT, $src", LoadStore,
|
def v16i8: LoadAFormVec<v16i8>;
|
||||||
[(set GPRC:$rT, (load dform_addr:$src))]>;
|
def v8i16: LoadAFormVec<v8i16>;
|
||||||
|
def v4i32: LoadAFormVec<v4i32>;
|
||||||
|
def v2i64: LoadAFormVec<v2i64>;
|
||||||
|
def v4f32: LoadAFormVec<v4f32>;
|
||||||
|
def v2f64: LoadAFormVec<v2f64>;
|
||||||
|
|
||||||
def LQDr64:
|
def r128: LoadAForm<GPRC>;
|
||||||
RI10Form<0b00101100, (outs R64C:$rT), (ins memri10:$src),
|
def r64: LoadAForm<R64C>;
|
||||||
"lqd\t$rT, $src", LoadStore,
|
def r32: LoadAForm<R32C>;
|
||||||
[(set R64C:$rT, (load dform_addr:$src))]>;
|
def f32: LoadAForm<R32FP>;
|
||||||
|
def f64: LoadAForm<R64FP>;
|
||||||
|
def r16: LoadAForm<R16C>;
|
||||||
|
def r8: LoadAForm<R8C>;
|
||||||
|
}
|
||||||
|
|
||||||
def LQDr32:
|
class LoadXFormVec<ValueType vectype>
|
||||||
RI10Form<0b00101100, (outs R32C:$rT), (ins memri10:$src),
|
: RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
|
||||||
"lqd\t$rT, $src", LoadStore,
|
"lqx\t$rT, $src",
|
||||||
[(set R32C:$rT, (load dform_addr:$src))]>;
|
LoadStore,
|
||||||
|
[(set (vectype VECREG:$rT), (load xform_addr:$src))]>
|
||||||
|
{ }
|
||||||
|
|
||||||
// Floating Point
|
class LoadXForm<RegisterClass rclass>
|
||||||
def LQDf32:
|
: RRForm<0b00100011100, (outs rclass:$rT), (ins memrr:$src),
|
||||||
RI10Form<0b00101100, (outs R32FP:$rT), (ins memri10:$src),
|
"lqx\t$rT, $src",
|
||||||
"lqd\t$rT, $src", LoadStore,
|
LoadStore,
|
||||||
[(set R32FP:$rT, (load dform_addr:$src))]>;
|
[(set rclass:$rT, (load xform_addr:$src))]>
|
||||||
|
{ }
|
||||||
|
|
||||||
def LQDf64:
|
multiclass LoadXForms
|
||||||
RI10Form<0b00101100, (outs R64FP:$rT), (ins memri10:$src),
|
{
|
||||||
"lqd\t$rT, $src", LoadStore,
|
def v16i8: LoadXFormVec<v16i8>;
|
||||||
[(set R64FP:$rT, (load dform_addr:$src))]>;
|
def v8i16: LoadXFormVec<v8i16>;
|
||||||
// END Floating Point
|
def v4i32: LoadXFormVec<v4i32>;
|
||||||
|
def v2i64: LoadXFormVec<v2i64>;
|
||||||
|
def v4f32: LoadXFormVec<v4f32>;
|
||||||
|
def v2f64: LoadXFormVec<v2f64>;
|
||||||
|
|
||||||
def LQDr16:
|
def r128: LoadXForm<GPRC>;
|
||||||
RI10Form<0b00101100, (outs R16C:$rT), (ins memri10:$src),
|
def r64: LoadXForm<R64C>;
|
||||||
"lqd\t$rT, $src", LoadStore,
|
def r32: LoadXForm<R32C>;
|
||||||
[(set R16C:$rT, (load dform_addr:$src))]>;
|
def f32: LoadXForm<R32FP>;
|
||||||
|
def f64: LoadXForm<R64FP>;
|
||||||
|
def r16: LoadXForm<R16C>;
|
||||||
|
def r8: LoadXForm<R8C>;
|
||||||
|
}
|
||||||
|
|
||||||
def LQDr8:
|
defm LQA : LoadAForms;
|
||||||
RI10Form<0b00101100, (outs R8C:$rT), (ins memri10:$src),
|
defm LQD : LoadDForms;
|
||||||
"lqd\t$rT, $src", LoadStore,
|
defm LQX : LoadXForms;
|
||||||
[(set R8C:$rT, (load dform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAv16i8:
|
|
||||||
RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set (v16i8 VECREG:$rT), (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAv8i16:
|
|
||||||
RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set (v8i16 VECREG:$rT), (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAv4i32:
|
|
||||||
RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set (v4i32 VECREG:$rT), (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAv2i64:
|
|
||||||
RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set (v2i64 VECREG:$rT), (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAv4f32:
|
|
||||||
RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set (v4f32 VECREG:$rT), (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAv2f64:
|
|
||||||
RI16Form<0b100001100, (outs VECREG:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set (v2f64 VECREG:$rT), (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAr128:
|
|
||||||
RI16Form<0b100001100, (outs GPRC:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set GPRC:$rT, (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAr64:
|
|
||||||
RI16Form<0b100001100, (outs R64C:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set R64C:$rT, (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAr32:
|
|
||||||
RI16Form<0b100001100, (outs R32C:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set R32C:$rT, (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAf32:
|
|
||||||
RI16Form<0b100001100, (outs R32FP:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set R32FP:$rT, (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAf64:
|
|
||||||
RI16Form<0b100001100, (outs R64FP:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set R64FP:$rT, (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAr16:
|
|
||||||
RI16Form<0b100001100, (outs R16C:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set R16C:$rT, (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQAr8:
|
|
||||||
RI16Form<0b100001100, (outs R8C:$rT), (ins addr256k:$src),
|
|
||||||
"lqa\t$rT, $src", LoadStore,
|
|
||||||
[(set R8C:$rT, (load aform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXv16i8:
|
|
||||||
RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set (v16i8 VECREG:$rT), (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXv8i16:
|
|
||||||
RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set (v8i16 VECREG:$rT), (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXv4i32:
|
|
||||||
RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set (v4i32 VECREG:$rT), (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXv2i64:
|
|
||||||
RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set (v2i64 VECREG:$rT), (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXv4f32:
|
|
||||||
RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set (v4f32 VECREG:$rT), (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXv2f64:
|
|
||||||
RRForm<0b00100011100, (outs VECREG:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set (v2f64 VECREG:$rT), (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXr128:
|
|
||||||
RRForm<0b00100011100, (outs GPRC:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set GPRC:$rT, (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXr64:
|
|
||||||
RRForm<0b00100011100, (outs R64C:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set R64C:$rT, (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXr32:
|
|
||||||
RRForm<0b00100011100, (outs R32C:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set R32C:$rT, (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXf32:
|
|
||||||
RRForm<0b00100011100, (outs R32FP:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set R32FP:$rT, (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXf64:
|
|
||||||
RRForm<0b00100011100, (outs R64FP:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set R64FP:$rT, (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXr16:
|
|
||||||
RRForm<0b00100011100, (outs R16C:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set R16C:$rT, (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
def LQXr8:
|
|
||||||
RRForm<0b00100011100, (outs R8C:$rT), (ins memrr:$src),
|
|
||||||
"lqx\t$rT, $src", LoadStore,
|
|
||||||
[(set R8C:$rT, (load xform_addr:$src))]>;
|
|
||||||
|
|
||||||
/* Load quadword, PC relative: Not much use at this point in time.
|
/* Load quadword, PC relative: Not much use at this point in time.
|
||||||
Might be of use later for relocatable code.
|
Might be of use later for relocatable code. It's effectively the
|
||||||
|
same as LQA, but uses PC-relative addressing.
|
||||||
def LQR : RI16Form<0b111001100, (outs VECREG:$rT), (ins s16imm:$disp),
|
def LQR : RI16Form<0b111001100, (outs VECREG:$rT), (ins s16imm:$disp),
|
||||||
"lqr\t$rT, $disp", LoadStore,
|
"lqr\t$rT, $disp", LoadStore,
|
||||||
[(set VECREG:$rT, (load iaddr:$disp))]>;
|
[(set VECREG:$rT, (load iaddr:$disp))]>;
|
||||||
|
|
@ -256,174 +160,108 @@ let isSimpleLoad = 1 in {
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Stores:
|
// Stores:
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
class StoreDFormVec<ValueType vectype>
|
||||||
|
: RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
|
||||||
|
"stqd\t$rT, $src",
|
||||||
|
LoadStore,
|
||||||
|
[(store (vectype VECREG:$rT), dform_addr:$src)]>
|
||||||
|
{ }
|
||||||
|
|
||||||
def STQDv16i8 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
|
class StoreDForm<RegisterClass rclass>
|
||||||
"stqd\t$rT, $src", LoadStore,
|
: RI10Form<0b00100100, (outs), (ins rclass:$rT, memri10:$src),
|
||||||
[(store (v16i8 VECREG:$rT), dform_addr:$src)]>;
|
"stqd\t$rT, $src",
|
||||||
|
LoadStore,
|
||||||
|
[(store rclass:$rT, dform_addr:$src)]>
|
||||||
|
{ }
|
||||||
|
|
||||||
def STQDv8i16 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
|
multiclass StoreDForms
|
||||||
"stqd\t$rT, $src", LoadStore,
|
{
|
||||||
[(store (v8i16 VECREG:$rT), dform_addr:$src)]>;
|
def v16i8: StoreDFormVec<v16i8>;
|
||||||
|
def v8i16: StoreDFormVec<v8i16>;
|
||||||
|
def v4i32: StoreDFormVec<v4i32>;
|
||||||
|
def v2i64: StoreDFormVec<v2i64>;
|
||||||
|
def v4f32: StoreDFormVec<v4f32>;
|
||||||
|
def v2f64: StoreDFormVec<v2f64>;
|
||||||
|
|
||||||
def STQDv4i32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
|
def r128: StoreDForm<GPRC>;
|
||||||
"stqd\t$rT, $src", LoadStore,
|
def r64: StoreDForm<R64C>;
|
||||||
[(store (v4i32 VECREG:$rT), dform_addr:$src)]>;
|
def r32: StoreDForm<R32C>;
|
||||||
|
def f32: StoreDForm<R32FP>;
|
||||||
|
def f64: StoreDForm<R64FP>;
|
||||||
|
def r16: StoreDForm<R16C>;
|
||||||
|
def r8: StoreDForm<R8C>;
|
||||||
|
}
|
||||||
|
|
||||||
def STQDv2i64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
|
class StoreAFormVec<ValueType vectype>
|
||||||
"stqd\t$rT, $src", LoadStore,
|
: RI16Form<0b0010010, (outs), (ins VECREG:$rT, addr256k:$src),
|
||||||
[(store (v2i64 VECREG:$rT), dform_addr:$src)]>;
|
"stqa\t$rT, $src",
|
||||||
|
LoadStore,
|
||||||
|
[(store (vectype VECREG:$rT), aform_addr:$src)]>
|
||||||
|
{ }
|
||||||
|
|
||||||
def STQDv4f32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
|
class StoreAForm<RegisterClass rclass>
|
||||||
"stqd\t$rT, $src", LoadStore,
|
: RI16Form<0b001001, (outs), (ins rclass:$rT, addr256k:$src),
|
||||||
[(store (v4f32 VECREG:$rT), dform_addr:$src)]>;
|
"stqa\t$rT, $src",
|
||||||
|
LoadStore,
|
||||||
|
[(store rclass:$rT, aform_addr:$src)]>
|
||||||
|
{ }
|
||||||
|
|
||||||
def STQDv2f64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memri10:$src),
|
multiclass StoreAForms
|
||||||
"stqd\t$rT, $src", LoadStore,
|
{
|
||||||
[(store (v2f64 VECREG:$rT), dform_addr:$src)]>;
|
def v16i8: StoreAFormVec<v16i8>;
|
||||||
|
def v8i16: StoreAFormVec<v8i16>;
|
||||||
|
def v4i32: StoreAFormVec<v4i32>;
|
||||||
|
def v2i64: StoreAFormVec<v2i64>;
|
||||||
|
def v4f32: StoreAFormVec<v4f32>;
|
||||||
|
def v2f64: StoreAFormVec<v2f64>;
|
||||||
|
|
||||||
def STQDr128 : RI10Form<0b00100100, (outs), (ins GPRC:$rT, memri10:$src),
|
def r128: StoreAForm<GPRC>;
|
||||||
"stqd\t$rT, $src", LoadStore,
|
def r64: StoreAForm<R64C>;
|
||||||
[(store GPRC:$rT, dform_addr:$src)]>;
|
def r32: StoreAForm<R32C>;
|
||||||
|
def f32: StoreAForm<R32FP>;
|
||||||
|
def f64: StoreAForm<R64FP>;
|
||||||
|
def r16: StoreAForm<R16C>;
|
||||||
|
def r8: StoreAForm<R8C>;
|
||||||
|
}
|
||||||
|
|
||||||
def STQDr64 : RI10Form<0b00100100, (outs), (ins R64C:$rT, memri10:$src),
|
class StoreXFormVec<ValueType vectype>
|
||||||
"stqd\t$rT, $src", LoadStore,
|
: RRForm<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
|
||||||
[(store R64C:$rT, dform_addr:$src)]>;
|
"stqx\t$rT, $src",
|
||||||
|
LoadStore,
|
||||||
|
[(store (vectype VECREG:$rT), xform_addr:$src)]>
|
||||||
|
{ }
|
||||||
|
|
||||||
def STQDr32 : RI10Form<0b00100100, (outs), (ins R32C:$rT, memri10:$src),
|
class StoreXForm<RegisterClass rclass>
|
||||||
"stqd\t$rT, $src", LoadStore,
|
: RRForm<0b00100100, (outs), (ins rclass:$rT, memrr:$src),
|
||||||
[(store R32C:$rT, dform_addr:$src)]>;
|
"stqx\t$rT, $src",
|
||||||
|
LoadStore,
|
||||||
|
[(store rclass:$rT, xform_addr:$src)]>
|
||||||
|
{ }
|
||||||
|
|
||||||
// Floating Point
|
multiclass StoreXForms
|
||||||
def STQDf32 : RI10Form<0b00100100, (outs), (ins R32FP:$rT, memri10:$src),
|
{
|
||||||
"stqd\t$rT, $src", LoadStore,
|
def v16i8: StoreXFormVec<v16i8>;
|
||||||
[(store R32FP:$rT, dform_addr:$src)]>;
|
def v8i16: StoreXFormVec<v8i16>;
|
||||||
|
def v4i32: StoreXFormVec<v4i32>;
|
||||||
|
def v2i64: StoreXFormVec<v2i64>;
|
||||||
|
def v4f32: StoreXFormVec<v4f32>;
|
||||||
|
def v2f64: StoreXFormVec<v2f64>;
|
||||||
|
|
||||||
def STQDf64 : RI10Form<0b00100100, (outs), (ins R64FP:$rT, memri10:$src),
|
def r128: StoreXForm<GPRC>;
|
||||||
"stqd\t$rT, $src", LoadStore,
|
def r64: StoreXForm<R64C>;
|
||||||
[(store R64FP:$rT, dform_addr:$src)]>;
|
def r32: StoreXForm<R32C>;
|
||||||
|
def f32: StoreXForm<R32FP>;
|
||||||
|
def f64: StoreXForm<R64FP>;
|
||||||
|
def r16: StoreXForm<R16C>;
|
||||||
|
def r8: StoreXForm<R8C>;
|
||||||
|
}
|
||||||
|
|
||||||
def STQDr16 : RI10Form<0b00100100, (outs), (ins R16C:$rT, memri10:$src),
|
defm STQD : StoreDForms;
|
||||||
"stqd\t$rT, $src", LoadStore,
|
defm STQA : StoreAForms;
|
||||||
[(store R16C:$rT, dform_addr:$src)]>;
|
defm STQX : StoreXForms;
|
||||||
|
|
||||||
def STQDr8 : RI10Form<0b00100100, (outs), (ins R8C:$rT, memri10:$src),
|
|
||||||
"stqd\t$rT, $src", LoadStore,
|
|
||||||
[(store R8C:$rT, dform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAv16i8 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store (v16i8 VECREG:$rT), aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAv8i16 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store (v8i16 VECREG:$rT), aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAv4i32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store (v4i32 VECREG:$rT), aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAv2i64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store (v2i64 VECREG:$rT), aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAv4f32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store (v4f32 VECREG:$rT), aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAv2f64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store (v2f64 VECREG:$rT), aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAr128 : RI10Form<0b00100100, (outs), (ins GPRC:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store GPRC:$rT, aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAr64 : RI10Form<0b00100100, (outs), (ins R64C:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store R64C:$rT, aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAr32 : RI10Form<0b00100100, (outs), (ins R32C:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store R32C:$rT, aform_addr:$src)]>;
|
|
||||||
|
|
||||||
// Floating Point
|
|
||||||
def STQAf32 : RI10Form<0b00100100, (outs), (ins R32FP:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store R32FP:$rT, aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAf64 : RI10Form<0b00100100, (outs), (ins R64FP:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store R64FP:$rT, aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAr16 : RI10Form<0b00100100, (outs), (ins R16C:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store R16C:$rT, aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQAr8 : RI10Form<0b00100100, (outs), (ins R8C:$rT, addr256k:$src),
|
|
||||||
"stqa\t$rT, $src", LoadStore,
|
|
||||||
[(store R8C:$rT, aform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXv16i8 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store (v16i8 VECREG:$rT), xform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXv8i16 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store (v8i16 VECREG:$rT), xform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXv4i32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store (v4i32 VECREG:$rT), xform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXv2i64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store (v2i64 VECREG:$rT), xform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXv4f32 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store (v4f32 VECREG:$rT), xform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXv2f64 : RI10Form<0b00100100, (outs), (ins VECREG:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store (v2f64 VECREG:$rT), xform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXr128 : RI10Form<0b00100100, (outs), (ins GPRC:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store GPRC:$rT, xform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXr64:
|
|
||||||
RI10Form<0b00100100, (outs), (ins R64C:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store R64C:$rT, xform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXr32:
|
|
||||||
RI10Form<0b00100100, (outs), (ins R32C:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store R32C:$rT, xform_addr:$src)]>;
|
|
||||||
|
|
||||||
// Floating Point
|
|
||||||
def STQXf32:
|
|
||||||
RI10Form<0b00100100, (outs), (ins R32FP:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store R32FP:$rT, xform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXf64:
|
|
||||||
RI10Form<0b00100100, (outs), (ins R64FP:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store R64FP:$rT, xform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXr16:
|
|
||||||
RI10Form<0b00100100, (outs), (ins R16C:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store R16C:$rT, xform_addr:$src)]>;
|
|
||||||
|
|
||||||
def STQXr8:
|
|
||||||
RI10Form<0b00100100, (outs), (ins R8C:$rT, memrr:$src),
|
|
||||||
"stqx\t$rT, $src", LoadStore,
|
|
||||||
[(store R8C:$rT, xform_addr:$src)]>;
|
|
||||||
|
|
||||||
/* Store quadword, PC relative: Not much use at this point in time. Might
|
/* Store quadword, PC relative: Not much use at this point in time. Might
|
||||||
be useful for relocatable code.
|
be useful for relocatable code.
|
||||||
def STQR : RI16Form<0b111000100, (outs), (ins VECREG:$rT, s16imm:$disp),
|
def STQR : RI16Form<0b111000100, (outs), (ins VECREG:$rT, s16imm:$disp),
|
||||||
"stqr\t$rT, $disp", LoadStore,
|
"stqr\t$rT, $disp", LoadStore,
|
||||||
[(store VECREG:$rT, iaddr:$disp)]>;
|
[(store VECREG:$rT, iaddr:$disp)]>;
|
||||||
|
|
@ -620,17 +458,22 @@ def IOHLlo:
|
||||||
// Form select mask for bytes using immediate, used in conjunction with the
|
// Form select mask for bytes using immediate, used in conjunction with the
|
||||||
// SELB instruction:
|
// SELB instruction:
|
||||||
|
|
||||||
def FSMBIv16i8 : RI16Form<0b101001100, (outs VECREG:$rT), (ins u16imm:$val),
|
class FSMBIVec<ValueType vectype>
|
||||||
"fsmbi\t$rT, $val", SelectOp,
|
: RI16Form<0b101001100, (outs VECREG:$rT), (ins u16imm:$val),
|
||||||
[(set (v16i8 VECREG:$rT), (SPUfsmbi_v16i8 immU16:$val))]>;
|
"fsmbi\t$rT, $val",
|
||||||
|
SelectOp,
|
||||||
|
[(set (vectype VECREG:$rT), (SPUfsmbi immU16:$val))]>
|
||||||
|
{ }
|
||||||
|
|
||||||
def FSMBIv8i16 : RI16Form<0b101001100, (outs VECREG:$rT), (ins u16imm:$val),
|
multiclass FSMBIs
|
||||||
"fsmbi\t$rT, $val", SelectOp,
|
{
|
||||||
[(set (v8i16 VECREG:$rT), (SPUfsmbi_v8i16 immU16:$val))]>;
|
def v16i8: FSMBIVec<v16i8>;
|
||||||
|
def v8i16: FSMBIVec<v8i16>;
|
||||||
|
def v4i32: FSMBIVec<v4i32>;
|
||||||
|
def v2i64: FSMBIVec<v2i64>;
|
||||||
|
}
|
||||||
|
|
||||||
def FSMBIvecv4i32 : RI16Form<0b101001100, (outs VECREG:$rT), (ins u16imm:$val),
|
defm FSMBI : FSMBIs;
|
||||||
"fsmbi\t$rT, $val", SelectOp,
|
|
||||||
[(set (v4i32 VECREG:$rT), (SPUfsmbi_v4i32 immU16:$val))]>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Integer and Logical Operations:
|
// Integer and Logical Operations:
|
||||||
|
|
@ -2762,17 +2605,17 @@ def CEQHIv8i16:
|
||||||
def CEQr32:
|
def CEQr32:
|
||||||
RRForm<0b00000011110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
|
RRForm<0b00000011110, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
|
||||||
"ceq\t$rT, $rA, $rB", ByteOp,
|
"ceq\t$rT, $rA, $rB", ByteOp,
|
||||||
[/* no pattern to match: intrinsic */]>;
|
[(set R32C:$rT, (seteq R32C:$rA, R32C:$rB))]>;
|
||||||
|
|
||||||
def CEQv4i32:
|
def CEQv4i32:
|
||||||
RRForm<0b00000011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
|
RRForm<0b00000011110, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
|
||||||
"ceq\t$rT, $rA, $rB", ByteOp,
|
"ceq\t$rT, $rA, $rB", ByteOp,
|
||||||
[/* no pattern to match: intrinsic */]>;
|
[(set (v4i32 VECREG:$rT), (seteq (v4i32 VECREG:$rA), (v4i32 VECREG:$rB)))]>;
|
||||||
|
|
||||||
def CEQIr32:
|
def CEQIr32:
|
||||||
RI10Form<0b00111110, (outs R32C:$rT), (ins R32C:$rA, s10imm:$val),
|
RI10Form<0b00111110, (outs R32C:$rT), (ins R32C:$rA, s10imm_i32:$val),
|
||||||
"ceqi\t$rT, $rA, $val", ByteOp,
|
"ceqi\t$rT, $rA, $val", ByteOp,
|
||||||
[/* no pattern to match: intrinsic */]>;
|
[(set R32C:$rT, (seteq R32C:$rA, i32ImmSExt10:$val))]>;
|
||||||
|
|
||||||
def CEQIv4i32:
|
def CEQIv4i32:
|
||||||
RI10Form<0b00111110, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
|
RI10Form<0b00111110, (outs VECREG:$rT), (ins VECREG:$rA, s10imm:$val),
|
||||||
|
|
@ -2872,18 +2715,29 @@ let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1 in {
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// brcond predicates:
|
// setcc and brcond patterns:
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
def : Pat<(brcond (i16 (seteq R16C:$rA, 0)), bb:$dest),
|
def : Pat<(brcond (i16 (seteq R16C:$rA, 0)), bb:$dest),
|
||||||
(BRHZ R16C:$rA, bb:$dest)>;
|
(BRHZ R16C:$rA, bb:$dest)>;
|
||||||
def : Pat<(brcond (i16 (setne R16C:$rA, 0)), bb:$dest),
|
|
||||||
(BRHNZ R16C:$rA, bb:$dest)>;
|
|
||||||
|
|
||||||
def : Pat<(brcond (i32 (seteq R32C:$rA, 0)), bb:$dest),
|
def : Pat<(brcond (i32 (seteq R32C:$rA, 0)), bb:$dest),
|
||||||
(BRZ R32C:$rA, bb:$dest)>;
|
(BRZ R32C:$rA, bb:$dest)>;
|
||||||
|
|
||||||
|
def : Pat<(brcond (i16 (setne R16C:$rA, 0)), bb:$dest),
|
||||||
|
(BRHNZ R16C:$rA, bb:$dest)>;
|
||||||
def : Pat<(brcond (i32 (setne R32C:$rA, 0)), bb:$dest),
|
def : Pat<(brcond (i32 (setne R32C:$rA, 0)), bb:$dest),
|
||||||
(BRNZ R32C:$rA, bb:$dest)>;
|
(BRNZ R32C:$rA, bb:$dest)>;
|
||||||
|
|
||||||
|
def : Pat<(brcond (i16 (setne R16C:$rA, i16ImmSExt10:$val)), bb:$dest),
|
||||||
|
(BRHNZ (CEQHIr16 R16C:$rA, i16ImmSExt10:$val), bb:$dest)>;
|
||||||
|
def : Pat<(brcond (i32 (setne R32C:$rA, i32ImmSExt10:$val)), bb:$dest),
|
||||||
|
(BRNZ (CEQIr32 R32C:$rA, i32ImmSExt10:$val), bb:$dest)>;
|
||||||
|
|
||||||
|
def : Pat<(brcond (i16 (setne R16C:$rA, R16C:$rB)), bb:$dest),
|
||||||
|
(BRHNZ (CEQHr16 R16C:$rA, R16:$rB), bb:$dest)>;
|
||||||
|
def : Pat<(brcond (i32 (setne R32C:$rA, R32C:$rB)), bb:$dest),
|
||||||
|
(BRNZ (CEQr32 R32C:$rA, R32C:$rB), bb:$dest)>;
|
||||||
|
|
||||||
let isTerminator = 1, isBarrier = 1 in {
|
let isTerminator = 1, isBarrier = 1 in {
|
||||||
let isReturn = 1 in {
|
let isReturn = 1 in {
|
||||||
def RET:
|
def RET:
|
||||||
|
|
@ -3460,24 +3314,42 @@ def : Pat<(i32 (anyext R16C:$rSrc)),
|
||||||
(ORI2To4 R16C:$rSrc, 0)>;
|
(ORI2To4 R16C:$rSrc, 0)>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Address translation: SPU, like PPC, has to split addresses into high and
|
// Address generation: SPU, like PPC, has to split addresses into high and
|
||||||
// low parts in order to load them into a register.
|
// low parts in order to load them into a register.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
def : Pat<(SPUaform tglobaladdr:$in, 0), (ILAlsa tglobaladdr:$in)>;
|
def : Pat<(SPUaform tglobaladdr:$in, 0), (ILAlsa tglobaladdr:$in)>;
|
||||||
def : Pat<(SPUxform tglobaladdr:$in, 0),
|
def : Pat<(SPUaform texternalsym:$in, 0), (ILAlsa texternalsym:$in)>;
|
||||||
|
def : Pat<(SPUaform tjumptable:$in, 0), (ILAlsa tjumptable:$in)>;
|
||||||
|
def : Pat<(SPUaform tconstpool:$in, 0), (ILAlsa tconstpool:$in)>;
|
||||||
|
|
||||||
|
def : Pat<(SPUindirect (SPUhi tglobaladdr:$in, 0),
|
||||||
|
(SPUlo tglobaladdr:$in, 0)),
|
||||||
(IOHLlo (ILHUhi tglobaladdr:$in), tglobaladdr:$in)>;
|
(IOHLlo (ILHUhi tglobaladdr:$in), tglobaladdr:$in)>;
|
||||||
|
|
||||||
def : Pat<(SPUaform tjumptable:$in, 0), (ILAlsa tjumptable:$in)>;
|
def : Pat<(SPUindirect (SPUhi texternalsym:$in, 0),
|
||||||
def : Pat<(SPUxform tjumptable:$in, 0),
|
(SPUlo texternalsym:$in, 0)),
|
||||||
|
(IOHLlo (ILHUhi texternalsym:$in), texternalsym:$in)>;
|
||||||
|
|
||||||
|
def : Pat<(SPUindirect (SPUhi tjumptable:$in, 0),
|
||||||
|
(SPUlo tjumptable:$in, 0)),
|
||||||
(IOHLlo (ILHUhi tjumptable:$in), tjumptable:$in)>;
|
(IOHLlo (ILHUhi tjumptable:$in), tjumptable:$in)>;
|
||||||
|
|
||||||
def : Pat<(SPUhi tconstpool:$in , 0), (ILHUhi tconstpool:$in)>;
|
def : Pat<(SPUindirect (SPUhi tconstpool:$in, 0),
|
||||||
def : Pat<(SPUlo tconstpool:$in , 0), (ILAlsa tconstpool:$in)>;
|
(SPUlo tconstpool:$in, 0)),
|
||||||
def : Pat<(SPUaform tconstpool:$in, 0), (ILAlsa tconstpool:$in)>;
|
(IOHLlo (ILHUhi tconstpool:$in), tconstpool:$in)>;
|
||||||
// tblgen bug prevents this from working.
|
|
||||||
// def : Pat<(SPUxform tconstpool:$in, 0),
|
def : Pat<(add (SPUhi tglobaladdr:$in, 0), (SPUlo tglobaladdr:$in, 0)),
|
||||||
// (IOHLlo (ILHUhi tconstpool:$in), tconstpool:$in)>;
|
(IOHLlo (ILHUhi tglobaladdr:$in), tglobaladdr:$in)>;
|
||||||
|
|
||||||
|
def : Pat<(add (SPUhi texternalsym:$in, 0), (SPUlo texternalsym:$in, 0)),
|
||||||
|
(IOHLlo (ILHUhi texternalsym:$in), texternalsym:$in)>;
|
||||||
|
|
||||||
|
def : Pat<(add (SPUhi tjumptable:$in, 0), (SPUlo tjumptable:$in, 0)),
|
||||||
|
(IOHLlo (ILHUhi tjumptable:$in), tjumptable:$in)>;
|
||||||
|
|
||||||
|
def : Pat<(add (SPUhi tconstpool:$in, 0), (SPUlo tconstpool:$in, 0)),
|
||||||
|
(IOHLlo (ILHUhi tconstpool:$in), tconstpool:$in)>;
|
||||||
|
|
||||||
// Instrinsics:
|
// Instrinsics:
|
||||||
include "CellSDKIntrinsics.td"
|
include "CellSDKIntrinsics.td"
|
||||||
|
|
|
||||||
|
|
@ -58,14 +58,8 @@ def SPUv4i32_binop: SDTypeProfile<1, 2, [
|
||||||
|
|
||||||
// FSMBI type constraints: There are several variations for the various
|
// FSMBI type constraints: There are several variations for the various
|
||||||
// vector types (this avoids having to bit_convert all over the place.)
|
// vector types (this avoids having to bit_convert all over the place.)
|
||||||
def SPUfsmbi_type_v16i8: SDTypeProfile<1, 1, [
|
def SPUfsmbi_type: SDTypeProfile<1, 1, [
|
||||||
SDTCisVT<0, v16i8>, SDTCisVT<1, i32>]>;
|
SDTCisVT<1, i32>]>;
|
||||||
|
|
||||||
def SPUfsmbi_type_v8i16: SDTypeProfile<1, 1, [
|
|
||||||
SDTCisVT<0, v8i16>, SDTCisVT<1, i32>]>;
|
|
||||||
|
|
||||||
def SPUfsmbi_type_v4i32: SDTypeProfile<1, 1, [
|
|
||||||
SDTCisVT<0, v4i32>, SDTCisVT<1, i32>]>;
|
|
||||||
|
|
||||||
// SELB type constraints:
|
// SELB type constraints:
|
||||||
def SPUselb_type_v16i8: SDTypeProfile<1, 3, [
|
def SPUselb_type_v16i8: SDTypeProfile<1, 3, [
|
||||||
|
|
@ -148,9 +142,7 @@ def SPUrotbytes_left_chained : SDNode<"SPUISD::ROTBYTES_LEFT_CHAINED",
|
||||||
SPUvecshift_type_v16i8, [SDNPHasChain]>;
|
SPUvecshift_type_v16i8, [SDNPHasChain]>;
|
||||||
|
|
||||||
// SPU form select mask for bytes, immediate
|
// SPU form select mask for bytes, immediate
|
||||||
def SPUfsmbi_v16i8: SDNode<"SPUISD::FSMBI", SPUfsmbi_type_v16i8, []>;
|
def SPUfsmbi: SDNode<"SPUISD::FSMBI", SPUfsmbi_type, []>;
|
||||||
def SPUfsmbi_v8i16: SDNode<"SPUISD::FSMBI", SPUfsmbi_type_v8i16, []>;
|
|
||||||
def SPUfsmbi_v4i32: SDNode<"SPUISD::FSMBI", SPUfsmbi_type_v4i32, []>;
|
|
||||||
|
|
||||||
// SPU select bits instruction
|
// SPU select bits instruction
|
||||||
def SPUselb_v16i8: SDNode<"SPUISD::SELB", SPUselb_type_v16i8, []>;
|
def SPUselb_v16i8: SDNode<"SPUISD::SELB", SPUselb_type_v16i8, []>;
|
||||||
|
|
@ -189,11 +181,8 @@ def SPUpcrel : SDNode<"SPUISD::PCRelAddr", SDTIntBinOp, []>;
|
||||||
// A-Form local store addresses
|
// A-Form local store addresses
|
||||||
def SPUaform : SDNode<"SPUISD::AFormAddr", SDTIntBinOp, []>;
|
def SPUaform : SDNode<"SPUISD::AFormAddr", SDTIntBinOp, []>;
|
||||||
|
|
||||||
// D-Form "imm($reg)" addresses
|
// Indirect [D-Form "imm($reg)" and X-Form "$reg($reg)"] addresses
|
||||||
def SPUdform : SDNode<"SPUISD::DFormAddr", SDTIntBinOp, []>;
|
def SPUindirect : SDNode<"SPUISD::IndirectAddr", SDTIntBinOp, []>;
|
||||||
|
|
||||||
// X-Form "$reg($reg)" addresses
|
|
||||||
def SPUxform : SDNode<"SPUISD::XFormAddr", SDTIntBinOp, []>;
|
|
||||||
|
|
||||||
// Load result node
|
// Load result node
|
||||||
def SPUload_result : SDTypeProfile<1, 3, []>;
|
def SPUload_result : SDTypeProfile<1, 3, []>;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
SPUTargetAsmInfo::SPUTargetAsmInfo(const SPUTargetMachine &TM) {
|
SPUTargetAsmInfo::SPUTargetAsmInfo(const SPUTargetMachine &TM) {
|
||||||
|
PCSymbol = ".";
|
||||||
CommentString = "#";
|
CommentString = "#";
|
||||||
GlobalPrefix = "";
|
GlobalPrefix = "";
|
||||||
PrivateGlobalPrefix = ".L";
|
PrivateGlobalPrefix = ".L";
|
||||||
|
|
@ -24,17 +25,14 @@ SPUTargetAsmInfo::SPUTargetAsmInfo(const SPUTargetMachine &TM) {
|
||||||
SetDirective = "\t.set";
|
SetDirective = "\t.set";
|
||||||
Data64bitsDirective = "\t.quad\t";
|
Data64bitsDirective = "\t.quad\t";
|
||||||
AlignmentIsInBytes = false;
|
AlignmentIsInBytes = false;
|
||||||
SwitchToSectionDirective = "\t.section\t";
|
SwitchToSectionDirective = ".section\t";
|
||||||
ConstantPoolSection = "\t.const\t";
|
ConstantPoolSection = "\t.const\t";
|
||||||
JumpTableDataSection = ".const";
|
JumpTableDataSection = ".const";
|
||||||
CStringSection = "\t.cstring";
|
CStringSection = "\t.cstring";
|
||||||
LCOMMDirective = "\t.lcomm\t";
|
|
||||||
StaticCtorsSection = ".mod_init_func";
|
StaticCtorsSection = ".mod_init_func";
|
||||||
StaticDtorsSection = ".mod_term_func";
|
StaticDtorsSection = ".mod_term_func";
|
||||||
FourByteConstantSection = ".const";
|
FourByteConstantSection = ".const";
|
||||||
SixteenByteConstantSection = "\t.section\t.rodata.cst16,\"aM\",@progbits,16";
|
SixteenByteConstantSection = "\t.section\t.rodata.cst16,\"aM\",@progbits,16";
|
||||||
UsedDirective = "\t.no_dead_strip\t";
|
|
||||||
WeakRefDirective = "\t.weak_reference\t";
|
|
||||||
InlineAsmStart = "# InlineAsm Start";
|
InlineAsmStart = "# InlineAsm Start";
|
||||||
InlineAsmEnd = "# InlineAsm End";
|
InlineAsmEnd = "# InlineAsm End";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
|
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
|
||||||
; RUN: llvm-as -o - %s | llc -march=cellspu -mattr=large_mem > %t2.s
|
; RUN: llvm-as -o - %s | llc -march=cellspu -mattr=large_mem > %t2.s
|
||||||
; RUN: grep bisl %t1.s | count 7
|
; RUN: grep bisl %t1.s | count 7
|
||||||
; RUN: grep ila %t1.s | count 1
|
; RUN: grep ila %t1.s | count 1
|
||||||
; RUN: grep rotqbyi %t1.s | count 4
|
; RUN: grep rotqbyi %t1.s | count 4
|
||||||
; RUN: grep lqa %t1.s | count 5
|
; RUN: grep lqa %t1.s | count 1
|
||||||
; RUN: grep lqd %t1.s | count 6
|
; RUN: grep lqd %t1.s | count 11
|
||||||
; RUN: grep dispatch_tab %t1.s | count 10
|
; RUN: grep dispatch_tab %t1.s | count 6
|
||||||
; RUN: grep bisl %t2.s | count 7
|
; RUN: grep bisl %t2.s | count 7
|
||||||
; RUN: grep ilhu %t2.s | count 2
|
; RUN: grep ilhu %t2.s | count 2
|
||||||
; RUN: grep iohl %t2.s | count 2
|
; RUN: grep iohl %t2.s | count 2
|
||||||
; RUN: grep rotqby %t2.s | count 6
|
; RUN: grep rotqby %t2.s | count 6
|
||||||
; RUN: grep lqd %t2.s | count 12
|
; RUN: grep lqd %t2.s | count 17
|
||||||
; RUN: grep lqx %t2.s | count 8
|
; RUN: grep il %t2.s | count 2
|
||||||
; RUN: grep il %t2.s | count 9
|
; RUN: grep ai %t2.s | count 7
|
||||||
; RUN: grep ai %t2.s | count 5
|
|
||||||
; RUN: grep dispatch_tab %t2.s | count 7
|
; RUN: grep dispatch_tab %t2.s | count 7
|
||||||
|
|
||||||
; ModuleID = 'call_indirect.bc'
|
; ModuleID = 'call_indirect.bc'
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
; RUN: llvm-as -o - %s | llc -march=cellspu -mattr=large_mem > %t2.s
|
; RUN: llvm-as -o - %s | llc -march=cellspu -mattr=large_mem > %t2.s
|
||||||
; RUN: grep shufb %t1.s | count 27
|
; RUN: grep shufb %t1.s | count 27
|
||||||
; RUN: grep lqa %t1.s | count 27
|
; RUN: grep lqa %t1.s | count 27
|
||||||
; RUN: grep lqx %t2.s | count 27
|
; RUN: grep lqd %t2.s | count 27
|
||||||
; RUN: grep space %t1.s | count 8
|
; RUN: grep space %t1.s | count 8
|
||||||
; RUN: grep byte %t1.s | count 424
|
; RUN: grep byte %t1.s | count 424
|
||||||
target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128"
|
target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
|
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
|
||||||
; RUN: grep fceq %t1.s | count 1 &&
|
; RUN: grep fceq %t1.s | count 1
|
||||||
; RUN: grep fcmeq %t1.s | count 1
|
; RUN: grep fcmeq %t1.s | count 1
|
||||||
;
|
;
|
||||||
; This file includes standard floating point arithmetic instructions
|
; This file includes standard floating point arithmetic instructions
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,26 @@
|
||||||
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
|
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
|
||||||
; RUN: llvm-as -o - %s | llc -march=cellspu -mattr=large_mem > %t2.s
|
; RUN: llvm-as -o - %s | llc -march=cellspu -mattr=large_mem > %t2.s
|
||||||
; RUN: grep lqa %t1.s | count 10
|
; RUN: grep lqa %t1.s | count 5
|
||||||
; RUN: grep lqd %t1.s | count 4
|
; RUN: grep lqd %t1.s | count 11
|
||||||
; RUN: grep rotqbyi %t1.s | count 5
|
; RUN: grep rotqbyi %t1.s | count 7
|
||||||
; RUN: grep xshw %t1.s | count 1
|
; RUN: grep xshw %t1.s | count 1
|
||||||
; RUN: grep andi %t1.s | count 4
|
; RUN: grep andi %t1.s | count 5
|
||||||
; RUN: grep cbd %t1.s | count 3
|
; RUN: grep cbd %t1.s | count 3
|
||||||
; RUN: grep chd %t1.s | count 1
|
; RUN: grep chd %t1.s | count 1
|
||||||
; RUN: grep cwd %t1.s | count 3
|
; RUN: grep cwd %t1.s | count 3
|
||||||
; RUN: grep shufb %t1.s | count 7
|
; RUN: grep shufb %t1.s | count 7
|
||||||
; RUN: grep stqa %t1.s | count 5
|
; RUN: grep stqd %t1.s | count 7
|
||||||
; RUN: grep iohl %t2.s | count 14
|
; RUN: grep iohl %t2.s | count 16
|
||||||
; RUN: grep ilhu %t2.s | count 14
|
; RUN: grep ilhu %t2.s | count 16
|
||||||
; RUN: grep lqx %t2.s | count 14
|
; RUN: grep lqd %t2.s | count 16
|
||||||
; RUN: grep rotqbyi %t2.s | count 5
|
; RUN: grep rotqbyi %t2.s | count 7
|
||||||
; RUN: grep xshw %t2.s | count 1
|
; RUN: grep xshw %t2.s | count 1
|
||||||
; RUN: grep andi %t2.s | count 4
|
; RUN: grep andi %t2.s | count 5
|
||||||
; RUN: grep cbx %t2.s | count 3
|
; RUN: grep cbd %t2.s | count 3
|
||||||
; RUN: grep chx %t2.s | count 1
|
; RUN: grep chd %t2.s | count 1
|
||||||
; RUN: grep cwx %t2.s | count 1
|
; RUN: grep cwd %t2.s | count 3
|
||||||
; RUN: grep cwd %t2.s | count 2
|
|
||||||
; RUN: grep shufb %t2.s | count 7
|
; RUN: grep shufb %t2.s | count 7
|
||||||
; RUN: grep stqx %t2.s | count 7
|
; RUN: grep stqd %t2.s | count 7
|
||||||
|
|
||||||
; ModuleID = 'struct_1.bc'
|
; ModuleID = 'struct_1.bc'
|
||||||
target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128"
|
target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128"
|
||||||
|
|
@ -48,88 +47,98 @@ target triple = "spu"
|
||||||
; struct hackstate state = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
; struct hackstate state = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||||
@state = global %struct.hackstate zeroinitializer, align 16
|
@state = global %struct.hackstate zeroinitializer, align 16
|
||||||
|
|
||||||
define i8 @get_hackstate_c1() zeroext {
|
define i8 @get_hackstate_c1() zeroext nounwind {
|
||||||
entry:
|
entry:
|
||||||
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 0), align 16
|
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 0), align 16
|
||||||
ret i8 %tmp2
|
ret i8 %tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
define i8 @get_hackstate_c2() zeroext {
|
define i8 @get_hackstate_c2() zeroext nounwind {
|
||||||
entry:
|
entry:
|
||||||
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 1), align 16
|
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 1), align 16
|
||||||
ret i8 %tmp2
|
ret i8 %tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
define i8 @get_hackstate_c3() zeroext {
|
define i8 @get_hackstate_c3() zeroext nounwind {
|
||||||
entry:
|
entry:
|
||||||
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 2), align 16
|
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 2), align 16
|
||||||
ret i8 %tmp2
|
ret i8 %tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
define i32 @get_hackstate_i1() {
|
define i32 @get_hackstate_i1() nounwind {
|
||||||
entry:
|
entry:
|
||||||
%tmp2 = load i32* getelementptr (%struct.hackstate* @state, i32 0, i32 3), align 16
|
%tmp2 = load i32* getelementptr (%struct.hackstate* @state, i32 0, i32 3), align 16
|
||||||
ret i32 %tmp2
|
ret i32 %tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
define i16 @get_hackstate_s1() signext {
|
define i16 @get_hackstate_s1() signext nounwind {
|
||||||
entry:
|
entry:
|
||||||
%tmp2 = load i16* getelementptr (%struct.hackstate* @state, i32 0, i32 4), align 16
|
%tmp2 = load i16* getelementptr (%struct.hackstate* @state, i32 0, i32 4), align 16
|
||||||
ret i16 %tmp2
|
ret i16 %tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
define i8 @get_hackstate_c7() zeroext {
|
define i8 @get_hackstate_c6() zeroext nounwind {
|
||||||
entry:
|
entry:
|
||||||
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 9), align 16
|
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 8), align 16
|
||||||
ret i8 %tmp2
|
ret i8 %tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
define i32 @get_hackstate_i6() zeroext {
|
define i8 @get_hackstate_c7() zeroext nounwind {
|
||||||
entry:
|
entry:
|
||||||
%tmp2 = load i32* getelementptr (%struct.hackstate* @state, i32 0, i32 13), align 16
|
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 9), align 16
|
||||||
ret i32 %tmp2
|
ret i8 %tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @set_hackstate_c1(i8 zeroext %c) {
|
define i32 @get_hackstate_i3() nounwind {
|
||||||
entry:
|
entry:
|
||||||
store i8 %c, i8* getelementptr (%struct.hackstate* @state, i32 0, i32 0), align 16
|
%tmp2 = load i32* getelementptr (%struct.hackstate* @state, i32 0, i32 10), align 16
|
||||||
ret void
|
ret i32 %tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @set_hackstate_c2(i8 zeroext %c) {
|
define i32 @get_hackstate_i6() nounwind {
|
||||||
entry:
|
entry:
|
||||||
store i8 %c, i8* getelementptr (%struct.hackstate* @state, i32 0, i32 1), align 16
|
%tmp2 = load i32* getelementptr (%struct.hackstate* @state, i32 0, i32 13), align 16
|
||||||
ret void
|
ret i32 %tmp2
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @set_hackstate_c3(i8 zeroext %c) {
|
define void @set_hackstate_c1(i8 zeroext %c) nounwind {
|
||||||
entry:
|
entry:
|
||||||
store i8 %c, i8* getelementptr (%struct.hackstate* @state, i32 0, i32 2), align 16
|
store i8 %c, i8* getelementptr (%struct.hackstate* @state, i32 0, i32 0), align 16
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @set_hackstate_i1(i32 %i) {
|
define void @set_hackstate_c2(i8 zeroext %c) nounwind {
|
||||||
entry:
|
entry:
|
||||||
store i32 %i, i32* getelementptr (%struct.hackstate* @state, i32 0, i32 3), align 16
|
store i8 %c, i8* getelementptr (%struct.hackstate* @state, i32 0, i32 1), align 16
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @set_hackstate_s1(i16 signext %s) {
|
define void @set_hackstate_c3(i8 zeroext %c) nounwind {
|
||||||
entry:
|
entry:
|
||||||
store i16 %s, i16* getelementptr (%struct.hackstate* @state, i32 0, i32 4), align 16
|
store i8 %c, i8* getelementptr (%struct.hackstate* @state, i32 0, i32 2), align 16
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
define void @set_hackstate_i3(i32 %i) {
|
define void @set_hackstate_i1(i32 %i) nounwind {
|
||||||
entry:
|
entry:
|
||||||
store i32 %i, i32* getelementptr (%struct.hackstate* @state, i32 0, i32 11), align 16
|
store i32 %i, i32* getelementptr (%struct.hackstate* @state, i32 0, i32 3), align 16
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define void @set_hackstate_s1(i16 signext %s) nounwind {
|
||||||
define void @set_hackstate_i6(i32 %i) {
|
|
||||||
entry:
|
entry:
|
||||||
store i32 %i, i32* getelementptr (%struct.hackstate* @state, i32 0, i32 13), align 16
|
store i16 %s, i16* getelementptr (%struct.hackstate* @state, i32 0, i32 4), align 16
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define void @set_hackstate_i3(i32 %i) nounwind {
|
||||||
|
entry:
|
||||||
|
store i32 %i, i32* getelementptr (%struct.hackstate* @state, i32 0, i32 10), align 16
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @set_hackstate_i6(i32 %i) nounwind {
|
||||||
|
entry:
|
||||||
|
store i32 %i, i32* getelementptr (%struct.hackstate* @state, i32 0, i32 13), align 16
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
|
|
||||||
; RUN: grep lqx %t1.s | count 14
|
|
||||||
; RUN: grep rotqby %t1.s | count 7
|
|
||||||
; RUN: grep xshw %t1.s | count 1
|
|
||||||
; RUN: grep andi %t1.s | count 4
|
|
||||||
; RUN: grep cbx %t1.s | count 1
|
|
||||||
; RUN: grep cbd %t1.s | count 2
|
|
||||||
; RUN: grep chd %t1.s | count 1
|
|
||||||
; RUN: grep cwd %t1.s | count 3
|
|
||||||
; RUN: grep shufb %t1.s | count 7
|
|
||||||
; RUN: grep stqx %t1.s | count 7
|
|
||||||
|
|
||||||
; ModuleID = 'struct_1.bc'
|
|
||||||
target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128"
|
|
||||||
target triple = "spu"
|
|
||||||
|
|
||||||
; struct hackstate {
|
|
||||||
; unsigned char c1; // offset 0 (rotate left by 13 bytes to byte 3)
|
|
||||||
; unsigned char c2; // offset 1 (rotate left by 14 bytes to byte 3)
|
|
||||||
; unsigned char c3; // offset 2 (rotate left by 15 bytes to byte 3)
|
|
||||||
; int i1; // offset 4 (rotate left by 4 bytes to byte 0)
|
|
||||||
; short s1; // offset 8 (rotate left by 6 bytes to byte 2)
|
|
||||||
; int i2; // offset 12 [ignored]
|
|
||||||
; unsigned char c4; // offset 16 [ignored]
|
|
||||||
; unsigned char c5; // offset 17 [ignored]
|
|
||||||
; unsigned char c6; // offset 18 [ignored]
|
|
||||||
; unsigned char c7; // offset 19 (no rotate, in preferred slot)
|
|
||||||
; int i3; // offset 20 [ignored]
|
|
||||||
; int i4; // offset 24 [ignored]
|
|
||||||
; int i5; // offset 28 [ignored]
|
|
||||||
; int i6; // offset 32 (no rotate, in preferred slot)
|
|
||||||
; }
|
|
||||||
%struct.hackstate = type { i8, i8, i8, i32, i16, i32, i8, i8, i8, i8, i32, i32, i32, i32 }
|
|
||||||
|
|
||||||
; struct hackstate state = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
|
||||||
@state = global %struct.hackstate zeroinitializer, align 4
|
|
||||||
|
|
||||||
define i8 @get_hackstate_c1() zeroext {
|
|
||||||
entry:
|
|
||||||
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 0), align 4
|
|
||||||
ret i8 %tmp2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i8 @get_hackstate_c2() zeroext {
|
|
||||||
entry:
|
|
||||||
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 1), align 4
|
|
||||||
ret i8 %tmp2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i8 @get_hackstate_c3() zeroext {
|
|
||||||
entry:
|
|
||||||
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 2), align 4
|
|
||||||
ret i8 %tmp2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i32 @get_hackstate_i1() {
|
|
||||||
entry:
|
|
||||||
%tmp2 = load i32* getelementptr (%struct.hackstate* @state, i32 0, i32 3), align 4
|
|
||||||
ret i32 %tmp2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i16 @get_hackstate_s1() signext {
|
|
||||||
entry:
|
|
||||||
%tmp2 = load i16* getelementptr (%struct.hackstate* @state, i32 0, i32 4), align 4
|
|
||||||
ret i16 %tmp2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i8 @get_hackstate_c7() zeroext {
|
|
||||||
entry:
|
|
||||||
%tmp2 = load i8* getelementptr (%struct.hackstate* @state, i32 0, i32 9), align 4
|
|
||||||
ret i8 %tmp2
|
|
||||||
}
|
|
||||||
|
|
||||||
define i32 @get_hackstate_i6() zeroext {
|
|
||||||
entry:
|
|
||||||
%tmp2 = load i32* getelementptr (%struct.hackstate* @state, i32 0, i32 13), align 4
|
|
||||||
ret i32 %tmp2
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @set_hackstate_c1(i8 zeroext %c) {
|
|
||||||
entry:
|
|
||||||
store i8 %c, i8* getelementptr (%struct.hackstate* @state, i32 0, i32 0), align 4
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @set_hackstate_c2(i8 zeroext %c) {
|
|
||||||
entry:
|
|
||||||
store i8 %c, i8* getelementptr (%struct.hackstate* @state, i32 0, i32 1), align 4
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @set_hackstate_c3(i8 zeroext %c) {
|
|
||||||
entry:
|
|
||||||
store i8 %c, i8* getelementptr (%struct.hackstate* @state, i32 0, i32 2), align 4
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @set_hackstate_i1(i32 %i) {
|
|
||||||
entry:
|
|
||||||
store i32 %i, i32* getelementptr (%struct.hackstate* @state, i32 0, i32 3), align 4
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @set_hackstate_s1(i16 signext %s) {
|
|
||||||
entry:
|
|
||||||
store i16 %s, i16* getelementptr (%struct.hackstate* @state, i32 0, i32 4), align 4
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @set_hackstate_i3(i32 %i) {
|
|
||||||
entry:
|
|
||||||
store i32 %i, i32* getelementptr (%struct.hackstate* @state, i32 0, i32 11), align 4
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
define void @set_hackstate_i6(i32 %i) {
|
|
||||||
entry:
|
|
||||||
store i32 %i, i32* getelementptr (%struct.hackstate* @state, i32 0, i32 13), align 4
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
|
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
|
||||||
; RUN: llvm-as -o - %s | llc -march=cellspu -mattr=large_mem > %t2.s
|
; RUN: llvm-as -o - %s | llc -march=cellspu -mattr=large_mem > %t2.s
|
||||||
; RUN: grep il %t1.s | count 16
|
; RUN: grep il %t1.s | count 16
|
||||||
; RUN: grep ilhu %t1.s | count 8
|
; RUN: grep ilhu %t1.s | count 8
|
||||||
; RUN: grep ilh %t1.s | count 13
|
; RUN: grep ilh %t1.s | count 13
|
||||||
; RUN: grep iohl %t1.s | count 7
|
; RUN: grep iohl %t1.s | count 7
|
||||||
; RUN: grep lqa %t1.s | count 6
|
; RUN: grep lqa %t1.s | count 6
|
||||||
; RUN: grep 24672 %t1.s | count 2
|
; RUN: grep 24672 %t1.s | count 2
|
||||||
; RUN: grep 16429 %t1.s | count 1
|
; RUN: grep 16429 %t1.s | count 1
|
||||||
; RUN: grep 63572 %t1.s | count 1
|
; RUN: grep 63572 %t1.s | count 1
|
||||||
; RUN: grep 4660 %t1.s | count 1
|
; RUN: grep 4660 %t1.s | count 1
|
||||||
|
|
@ -17,8 +17,7 @@
|
||||||
; RUN: grep 21572 %t1.s | count 1
|
; RUN: grep 21572 %t1.s | count 1
|
||||||
; RUN: grep 11544 %t1.s | count 1
|
; RUN: grep 11544 %t1.s | count 1
|
||||||
; RUN: grep 1311768467750121234 %t1.s | count 1
|
; RUN: grep 1311768467750121234 %t1.s | count 1
|
||||||
; RUN: grep lqx %t2.s | count 6
|
; RUN: grep lqd %t2.s | count 6
|
||||||
; RUN: grep ila %t2.s | count 6
|
|
||||||
|
|
||||||
target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128"
|
target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128"
|
||||||
target triple = "spu-unknown-elf"
|
target triple = "spu-unknown-elf"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue