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:
Scott Michel 2008-01-29 02:16:57 +00:00
parent ce0740e1f5
commit ceae3bbf4d
14 changed files with 623 additions and 852 deletions

View File

@ -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;

View File

@ -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));

View File

@ -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();
} }

View File

@ -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

View File

@ -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>

View File

@ -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"

View File

@ -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, []>;

View File

@ -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";

View File

@ -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'

View File

@ -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"

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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"