mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-25 12:49:50 +00:00
Added support for FP conditional move instructions and fixed bugs in handling of FP comparisons.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128650 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5bb3eced65
commit
1d6b38d9d3
@ -41,10 +41,10 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||||||
case MipsISD::Lo : return "MipsISD::Lo";
|
case MipsISD::Lo : return "MipsISD::Lo";
|
||||||
case MipsISD::GPRel : return "MipsISD::GPRel";
|
case MipsISD::GPRel : return "MipsISD::GPRel";
|
||||||
case MipsISD::Ret : return "MipsISD::Ret";
|
case MipsISD::Ret : return "MipsISD::Ret";
|
||||||
case MipsISD::SelectCC : return "MipsISD::SelectCC";
|
|
||||||
case MipsISD::FPSelectCC : return "MipsISD::FPSelectCC";
|
|
||||||
case MipsISD::FPBrcond : return "MipsISD::FPBrcond";
|
case MipsISD::FPBrcond : return "MipsISD::FPBrcond";
|
||||||
case MipsISD::FPCmp : return "MipsISD::FPCmp";
|
case MipsISD::FPCmp : return "MipsISD::FPCmp";
|
||||||
|
case MipsISD::CMovFP_T : return "MipsISD::CMovFP_T";
|
||||||
|
case MipsISD::CMovFP_F : return "MipsISD::CMovFP_F";
|
||||||
case MipsISD::FPRound : return "MipsISD::FPRound";
|
case MipsISD::FPRound : return "MipsISD::FPRound";
|
||||||
case MipsISD::MAdd : return "MipsISD::MAdd";
|
case MipsISD::MAdd : return "MipsISD::MAdd";
|
||||||
case MipsISD::MAddu : return "MipsISD::MAddu";
|
case MipsISD::MAddu : return "MipsISD::MAddu";
|
||||||
@ -98,20 +98,11 @@ MipsTargetLowering(MipsTargetMachine &TM)
|
|||||||
setOperationAction(ISD::SELECT, MVT::f32, Custom);
|
setOperationAction(ISD::SELECT, MVT::f32, Custom);
|
||||||
setOperationAction(ISD::SELECT, MVT::f64, Custom);
|
setOperationAction(ISD::SELECT, MVT::f64, Custom);
|
||||||
setOperationAction(ISD::SELECT, MVT::i32, Custom);
|
setOperationAction(ISD::SELECT, MVT::i32, Custom);
|
||||||
setOperationAction(ISD::SETCC, MVT::f32, Custom);
|
|
||||||
setOperationAction(ISD::SETCC, MVT::f64, Custom);
|
|
||||||
setOperationAction(ISD::BRCOND, MVT::Other, Custom);
|
setOperationAction(ISD::BRCOND, MVT::Other, Custom);
|
||||||
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
|
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
|
||||||
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
|
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
|
||||||
setOperationAction(ISD::VASTART, MVT::Other, Custom);
|
setOperationAction(ISD::VASTART, MVT::Other, Custom);
|
||||||
|
|
||||||
|
|
||||||
// We custom lower AND/OR to handle the case where the DAG contain 'ands/ors'
|
|
||||||
// with operands comming from setcc fp comparions. This is necessary since
|
|
||||||
// the result from these setcc are in a flag registers (FCR31).
|
|
||||||
setOperationAction(ISD::AND, MVT::i32, Custom);
|
|
||||||
setOperationAction(ISD::OR, MVT::i32, Custom);
|
|
||||||
|
|
||||||
setOperationAction(ISD::SDIV, MVT::i32, Expand);
|
setOperationAction(ISD::SDIV, MVT::i32, Expand);
|
||||||
setOperationAction(ISD::SREM, MVT::i32, Expand);
|
setOperationAction(ISD::SREM, MVT::i32, Expand);
|
||||||
setOperationAction(ISD::UDIV, MVT::i32, Expand);
|
setOperationAction(ISD::UDIV, MVT::i32, Expand);
|
||||||
@ -176,6 +167,7 @@ MipsTargetLowering(MipsTargetMachine &TM)
|
|||||||
setTargetDAGCombine(ISD::SUBE);
|
setTargetDAGCombine(ISD::SUBE);
|
||||||
setTargetDAGCombine(ISD::SDIVREM);
|
setTargetDAGCombine(ISD::SDIVREM);
|
||||||
setTargetDAGCombine(ISD::UDIVREM);
|
setTargetDAGCombine(ISD::UDIVREM);
|
||||||
|
setTargetDAGCombine(ISD::SETCC);
|
||||||
|
|
||||||
setStackPointerRegisterToSaveRestore(Mips::SP);
|
setStackPointerRegisterToSaveRestore(Mips::SP);
|
||||||
computeRegisterProperties();
|
computeRegisterProperties();
|
||||||
@ -396,6 +388,96 @@ static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG,
|
|||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) {
|
||||||
|
switch (CC) {
|
||||||
|
default: llvm_unreachable("Unknown fp condition code!");
|
||||||
|
case ISD::SETEQ:
|
||||||
|
case ISD::SETOEQ: return Mips::FCOND_OEQ;
|
||||||
|
case ISD::SETUNE: return Mips::FCOND_UNE;
|
||||||
|
case ISD::SETLT:
|
||||||
|
case ISD::SETOLT: return Mips::FCOND_OLT;
|
||||||
|
case ISD::SETGT:
|
||||||
|
case ISD::SETOGT: return Mips::FCOND_OGT;
|
||||||
|
case ISD::SETLE:
|
||||||
|
case ISD::SETOLE: return Mips::FCOND_OLE;
|
||||||
|
case ISD::SETGE:
|
||||||
|
case ISD::SETOGE: return Mips::FCOND_OGE;
|
||||||
|
case ISD::SETULT: return Mips::FCOND_ULT;
|
||||||
|
case ISD::SETULE: return Mips::FCOND_ULE;
|
||||||
|
case ISD::SETUGT: return Mips::FCOND_UGT;
|
||||||
|
case ISD::SETUGE: return Mips::FCOND_UGE;
|
||||||
|
case ISD::SETUO: return Mips::FCOND_UN;
|
||||||
|
case ISD::SETO: return Mips::FCOND_OR;
|
||||||
|
case ISD::SETNE:
|
||||||
|
case ISD::SETONE: return Mips::FCOND_ONE;
|
||||||
|
case ISD::SETUEQ: return Mips::FCOND_UEQ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns true if condition code has to be inverted.
|
||||||
|
static bool InvertFPCondCode(Mips::CondCode CC) {
|
||||||
|
if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
assert(false && "Illegal Condition Code");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates and returns an FPCmp node from a setcc node.
|
||||||
|
// Returns Op if setcc is not a floating point comparison.
|
||||||
|
static SDValue CreateFPCmp(SelectionDAG& DAG, const SDValue& Op) {
|
||||||
|
// must be a SETCC node
|
||||||
|
if (Op.getOpcode() != ISD::SETCC)
|
||||||
|
return Op;
|
||||||
|
|
||||||
|
SDValue LHS = Op.getOperand(0);
|
||||||
|
|
||||||
|
if (!LHS.getValueType().isFloatingPoint())
|
||||||
|
return Op;
|
||||||
|
|
||||||
|
SDValue RHS = Op.getOperand(1);
|
||||||
|
DebugLoc dl = Op.getDebugLoc();
|
||||||
|
|
||||||
|
// Assume the 3rd operand is a CondCodeSDNode. Add code to check the type of node
|
||||||
|
// if necessary.
|
||||||
|
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
|
||||||
|
|
||||||
|
return DAG.getNode(MipsISD::FPCmp, dl, MVT::Glue, LHS, RHS,
|
||||||
|
DAG.getConstant(FPCondCCodeToFCC(CC), MVT::i32));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates and returns a CMovFPT/F node.
|
||||||
|
static SDValue CreateCMovFP(SelectionDAG& DAG, SDValue Cond, SDValue True,
|
||||||
|
SDValue False, DebugLoc DL) {
|
||||||
|
bool invert = InvertFPCondCode((Mips::CondCode)
|
||||||
|
cast<ConstantSDNode>(Cond.getOperand(2))
|
||||||
|
->getSExtValue());
|
||||||
|
|
||||||
|
return DAG.getNode((invert ? MipsISD::CMovFP_F : MipsISD::CMovFP_T), DL,
|
||||||
|
True.getValueType(), True, False, Cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDValue PerformSETCCCombine(SDNode *N, SelectionDAG& DAG,
|
||||||
|
TargetLowering::DAGCombinerInfo &DCI,
|
||||||
|
const MipsSubtarget* Subtarget) {
|
||||||
|
if (DCI.isBeforeLegalizeOps())
|
||||||
|
return SDValue();
|
||||||
|
|
||||||
|
SDValue Cond = CreateFPCmp(DAG, SDValue(N, 0));
|
||||||
|
|
||||||
|
if (Cond.getOpcode() != MipsISD::FPCmp)
|
||||||
|
return SDValue();
|
||||||
|
|
||||||
|
SDValue True = DAG.getConstant(1, MVT::i32);
|
||||||
|
SDValue False = DAG.getConstant(0, MVT::i32);
|
||||||
|
|
||||||
|
return CreateCMovFP(DAG, Cond, True, False, N->getDebugLoc());
|
||||||
|
}
|
||||||
|
|
||||||
SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
|
SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
|
||||||
const {
|
const {
|
||||||
SelectionDAG &DAG = DCI.DAG;
|
SelectionDAG &DAG = DCI.DAG;
|
||||||
@ -410,6 +492,8 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
|
|||||||
case ISD::SDIVREM:
|
case ISD::SDIVREM:
|
||||||
case ISD::UDIVREM:
|
case ISD::UDIVREM:
|
||||||
return PerformDivRemCombine(N, DAG, DCI, Subtarget);
|
return PerformDivRemCombine(N, DAG, DCI, Subtarget);
|
||||||
|
case ISD::SETCC:
|
||||||
|
return PerformSETCCCombine(N, DAG, DCI, Subtarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SDValue();
|
return SDValue();
|
||||||
@ -420,7 +504,6 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
|
|||||||
{
|
{
|
||||||
switch (Op.getOpcode())
|
switch (Op.getOpcode())
|
||||||
{
|
{
|
||||||
case ISD::AND: return LowerANDOR(Op, DAG);
|
|
||||||
case ISD::BRCOND: return LowerBRCOND(Op, DAG);
|
case ISD::BRCOND: return LowerBRCOND(Op, DAG);
|
||||||
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
|
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
|
||||||
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
||||||
@ -429,9 +512,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
|
|||||||
case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
|
case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
|
||||||
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
|
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
|
||||||
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
|
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
|
||||||
case ISD::OR: return LowerANDOR(Op, DAG);
|
|
||||||
case ISD::SELECT: return LowerSELECT(Op, DAG);
|
case ISD::SELECT: return LowerSELECT(Op, DAG);
|
||||||
case ISD::SETCC: return LowerSETCC(Op, DAG);
|
|
||||||
case ISD::VASTART: return LowerVASTART(Op, DAG);
|
case ISD::VASTART: return LowerVASTART(Op, DAG);
|
||||||
}
|
}
|
||||||
return SDValue();
|
return SDValue();
|
||||||
@ -464,122 +545,110 @@ static Mips::FPBranchCode GetFPBranchCodeFromCond(Mips::CondCode CC) {
|
|||||||
return Mips::BRANCH_INVALID;
|
return Mips::BRANCH_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned FPBranchCodeToOpc(Mips::FPBranchCode BC) {
|
|
||||||
switch(BC) {
|
|
||||||
default:
|
|
||||||
llvm_unreachable("Unknown branch code");
|
|
||||||
case Mips::BRANCH_T : return Mips::BC1T;
|
|
||||||
case Mips::BRANCH_F : return Mips::BC1F;
|
|
||||||
case Mips::BRANCH_TL : return Mips::BC1TL;
|
|
||||||
case Mips::BRANCH_FL : return Mips::BC1FL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) {
|
|
||||||
switch (CC) {
|
|
||||||
default: llvm_unreachable("Unknown fp condition code!");
|
|
||||||
case ISD::SETEQ:
|
|
||||||
case ISD::SETOEQ: return Mips::FCOND_EQ;
|
|
||||||
case ISD::SETUNE: return Mips::FCOND_OGL;
|
|
||||||
case ISD::SETLT:
|
|
||||||
case ISD::SETOLT: return Mips::FCOND_OLT;
|
|
||||||
case ISD::SETGT:
|
|
||||||
case ISD::SETOGT: return Mips::FCOND_OGT;
|
|
||||||
case ISD::SETLE:
|
|
||||||
case ISD::SETOLE: return Mips::FCOND_OLE;
|
|
||||||
case ISD::SETGE:
|
|
||||||
case ISD::SETOGE: return Mips::FCOND_OGE;
|
|
||||||
case ISD::SETULT: return Mips::FCOND_ULT;
|
|
||||||
case ISD::SETULE: return Mips::FCOND_ULE;
|
|
||||||
case ISD::SETUGT: return Mips::FCOND_UGT;
|
|
||||||
case ISD::SETUGE: return Mips::FCOND_UGE;
|
|
||||||
case ISD::SETUO: return Mips::FCOND_UN;
|
|
||||||
case ISD::SETO: return Mips::FCOND_OR;
|
|
||||||
case ISD::SETNE:
|
|
||||||
case ISD::SETONE: return Mips::FCOND_NEQ;
|
|
||||||
case ISD::SETUEQ: return Mips::FCOND_UEQ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MachineBasicBlock *
|
MachineBasicBlock *
|
||||||
MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||||
MachineBasicBlock *BB) const {
|
MachineBasicBlock *BB) const {
|
||||||
|
// There is no need to expand CMov instructions if target has
|
||||||
|
// conditional moves.
|
||||||
|
if (Subtarget->hasCondMov())
|
||||||
|
return BB;
|
||||||
|
|
||||||
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
|
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
|
||||||
bool isFPCmp = false;
|
bool isFPCmp = false;
|
||||||
DebugLoc dl = MI->getDebugLoc();
|
DebugLoc dl = MI->getDebugLoc();
|
||||||
|
unsigned Opc;
|
||||||
|
|
||||||
switch (MI->getOpcode()) {
|
switch (MI->getOpcode()) {
|
||||||
default: assert(false && "Unexpected instr type to insert");
|
default: assert(false && "Unexpected instr type to insert");
|
||||||
case Mips::Select_FCC:
|
case Mips::MOVT:
|
||||||
case Mips::Select_FCC_S32:
|
case Mips::MOVT_S:
|
||||||
case Mips::Select_FCC_D32:
|
case Mips::MOVT_D:
|
||||||
isFPCmp = true; // FALL THROUGH
|
isFPCmp = true;
|
||||||
case Mips::Select_CC:
|
Opc = Mips::BC1F;
|
||||||
case Mips::Select_CC_S32:
|
break;
|
||||||
case Mips::Select_CC_D32: {
|
case Mips::MOVF:
|
||||||
// To "insert" a SELECT_CC instruction, we actually have to insert the
|
case Mips::MOVF_S:
|
||||||
// diamond control-flow pattern. The incoming instruction knows the
|
case Mips::MOVF_D:
|
||||||
// destination vreg to set, the condition code register to branch on, the
|
isFPCmp = true;
|
||||||
// true/false values to select between, and a branch opcode to use.
|
Opc = Mips::BC1T;
|
||||||
const BasicBlock *LLVM_BB = BB->getBasicBlock();
|
break;
|
||||||
MachineFunction::iterator It = BB;
|
case Mips::MOVZ_I:
|
||||||
++It;
|
case Mips::MOVZ_S:
|
||||||
|
case Mips::MOVZ_D:
|
||||||
|
Opc = Mips::BNE;
|
||||||
|
break;
|
||||||
|
case Mips::MOVN_I:
|
||||||
|
case Mips::MOVN_S:
|
||||||
|
case Mips::MOVN_D:
|
||||||
|
Opc = Mips::BEQ;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// thisMBB:
|
// To "insert" a SELECT_CC instruction, we actually have to insert the
|
||||||
// ...
|
// diamond control-flow pattern. The incoming instruction knows the
|
||||||
// TrueVal = ...
|
// destination vreg to set, the condition code register to branch on, the
|
||||||
// setcc r1, r2, r3
|
// true/false values to select between, and a branch opcode to use.
|
||||||
// bNE r1, r0, copy1MBB
|
const BasicBlock *LLVM_BB = BB->getBasicBlock();
|
||||||
// fallthrough --> copy0MBB
|
MachineFunction::iterator It = BB;
|
||||||
MachineBasicBlock *thisMBB = BB;
|
++It;
|
||||||
MachineFunction *F = BB->getParent();
|
|
||||||
MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
|
|
||||||
MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
|
|
||||||
F->insert(It, copy0MBB);
|
|
||||||
F->insert(It, sinkMBB);
|
|
||||||
|
|
||||||
// Transfer the remainder of BB and its successor edges to sinkMBB.
|
// thisMBB:
|
||||||
sinkMBB->splice(sinkMBB->begin(), BB,
|
// ...
|
||||||
llvm::next(MachineBasicBlock::iterator(MI)),
|
// TrueVal = ...
|
||||||
BB->end());
|
// setcc r1, r2, r3
|
||||||
sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
|
// bNE r1, r0, copy1MBB
|
||||||
|
// fallthrough --> copy0MBB
|
||||||
|
MachineBasicBlock *thisMBB = BB;
|
||||||
|
MachineFunction *F = BB->getParent();
|
||||||
|
MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
|
||||||
|
MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
|
||||||
|
F->insert(It, copy0MBB);
|
||||||
|
F->insert(It, sinkMBB);
|
||||||
|
|
||||||
// Next, add the true and fallthrough blocks as its successors.
|
// Transfer the remainder of BB and its successor edges to sinkMBB.
|
||||||
BB->addSuccessor(copy0MBB);
|
sinkMBB->splice(sinkMBB->begin(), BB,
|
||||||
BB->addSuccessor(sinkMBB);
|
llvm::next(MachineBasicBlock::iterator(MI)),
|
||||||
|
BB->end());
|
||||||
|
sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
|
||||||
|
|
||||||
// Emit the right instruction according to the type of the operands compared
|
// Next, add the true and fallthrough blocks as its successors.
|
||||||
if (isFPCmp) {
|
BB->addSuccessor(copy0MBB);
|
||||||
// Find the condiction code present in the setcc operation.
|
BB->addSuccessor(sinkMBB);
|
||||||
Mips::CondCode CC = (Mips::CondCode)MI->getOperand(4).getImm();
|
|
||||||
// Get the branch opcode from the branch code.
|
|
||||||
unsigned Opc = FPBranchCodeToOpc(GetFPBranchCodeFromCond(CC));
|
|
||||||
BuildMI(BB, dl, TII->get(Opc)).addMBB(sinkMBB);
|
|
||||||
} else
|
|
||||||
BuildMI(BB, dl, TII->get(Mips::BNE)).addReg(MI->getOperand(1).getReg())
|
|
||||||
.addReg(Mips::ZERO).addMBB(sinkMBB);
|
|
||||||
|
|
||||||
// copy0MBB:
|
// Emit the right instruction according to the type of the operands compared
|
||||||
// %FalseValue = ...
|
if (isFPCmp)
|
||||||
// # fallthrough to sinkMBB
|
BuildMI(BB, dl, TII->get(Opc)).addMBB(sinkMBB);
|
||||||
BB = copy0MBB;
|
else
|
||||||
|
BuildMI(BB, dl, TII->get(Opc)).addReg(MI->getOperand(2).getReg())
|
||||||
|
.addReg(Mips::ZERO).addMBB(sinkMBB);
|
||||||
|
|
||||||
// Update machine-CFG edges
|
|
||||||
BB->addSuccessor(sinkMBB);
|
|
||||||
|
|
||||||
// sinkMBB:
|
// copy0MBB:
|
||||||
// %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
|
// %FalseValue = ...
|
||||||
// ...
|
// # fallthrough to sinkMBB
|
||||||
BB = sinkMBB;
|
BB = copy0MBB;
|
||||||
|
|
||||||
|
// Update machine-CFG edges
|
||||||
|
BB->addSuccessor(sinkMBB);
|
||||||
|
|
||||||
|
// sinkMBB:
|
||||||
|
// %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
|
||||||
|
// ...
|
||||||
|
BB = sinkMBB;
|
||||||
|
|
||||||
|
if (isFPCmp)
|
||||||
BuildMI(*BB, BB->begin(), dl,
|
BuildMI(*BB, BB->begin(), dl,
|
||||||
TII->get(Mips::PHI), MI->getOperand(0).getReg())
|
TII->get(Mips::PHI), MI->getOperand(0).getReg())
|
||||||
.addReg(MI->getOperand(2).getReg()).addMBB(thisMBB)
|
.addReg(MI->getOperand(2).getReg()).addMBB(thisMBB)
|
||||||
.addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB);
|
.addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB);
|
||||||
|
else
|
||||||
|
BuildMI(*BB, BB->begin(), dl,
|
||||||
|
TII->get(Mips::PHI), MI->getOperand(0).getReg())
|
||||||
|
.addReg(MI->getOperand(3).getReg()).addMBB(thisMBB)
|
||||||
|
.addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB);
|
||||||
|
|
||||||
MI->eraseFromParent(); // The pseudo instruction is gone now.
|
MI->eraseFromParent(); // The pseudo instruction is gone now.
|
||||||
return BB;
|
return BB;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -643,27 +712,6 @@ LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
|
|||||||
return DAG.getMergeValues(Ops, 2, dl);
|
return DAG.getMergeValues(Ops, 2, dl);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue MipsTargetLowering::
|
|
||||||
LowerANDOR(SDValue Op, SelectionDAG &DAG) const
|
|
||||||
{
|
|
||||||
SDValue LHS = Op.getOperand(0);
|
|
||||||
SDValue RHS = Op.getOperand(1);
|
|
||||||
DebugLoc dl = Op.getDebugLoc();
|
|
||||||
|
|
||||||
if (LHS.getOpcode() != MipsISD::FPCmp || RHS.getOpcode() != MipsISD::FPCmp)
|
|
||||||
return Op;
|
|
||||||
|
|
||||||
SDValue True = DAG.getConstant(1, MVT::i32);
|
|
||||||
SDValue False = DAG.getConstant(0, MVT::i32);
|
|
||||||
|
|
||||||
SDValue LSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(),
|
|
||||||
LHS, True, False, LHS.getOperand(2));
|
|
||||||
SDValue RSEL = DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(),
|
|
||||||
RHS, True, False, RHS.getOperand(2));
|
|
||||||
|
|
||||||
return DAG.getNode(Op.getOpcode(), dl, MVT::i32, LSEL, RSEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDValue MipsTargetLowering::
|
SDValue MipsTargetLowering::
|
||||||
LowerBRCOND(SDValue Op, SelectionDAG &DAG) const
|
LowerBRCOND(SDValue Op, SelectionDAG &DAG) const
|
||||||
{
|
{
|
||||||
@ -673,58 +721,32 @@ LowerBRCOND(SDValue Op, SelectionDAG &DAG) const
|
|||||||
SDValue Dest = Op.getOperand(2);
|
SDValue Dest = Op.getOperand(2);
|
||||||
DebugLoc dl = Op.getDebugLoc();
|
DebugLoc dl = Op.getDebugLoc();
|
||||||
|
|
||||||
if (Op.getOperand(1).getOpcode() != MipsISD::FPCmp)
|
SDValue CondRes = CreateFPCmp(DAG, Op.getOperand(1));
|
||||||
|
|
||||||
|
// Return if flag is not set by a floating point comparision.
|
||||||
|
if (CondRes.getOpcode() != MipsISD::FPCmp)
|
||||||
return Op;
|
return Op;
|
||||||
|
|
||||||
SDValue CondRes = Op.getOperand(1);
|
|
||||||
SDValue CCNode = CondRes.getOperand(2);
|
SDValue CCNode = CondRes.getOperand(2);
|
||||||
Mips::CondCode CC =
|
Mips::CondCode CC =
|
||||||
(Mips::CondCode)cast<ConstantSDNode>(CCNode)->getZExtValue();
|
(Mips::CondCode)cast<ConstantSDNode>(CCNode)->getZExtValue();
|
||||||
SDValue BrCode = DAG.getConstant(GetFPBranchCodeFromCond(CC), MVT::i32);
|
SDValue BrCode = DAG.getConstant(GetFPBranchCodeFromCond(CC), MVT::i32);
|
||||||
|
|
||||||
return DAG.getNode(MipsISD::FPBrcond, dl, Op.getValueType(), Chain, BrCode,
|
return DAG.getNode(MipsISD::FPBrcond, dl, Op.getValueType(), Chain, BrCode,
|
||||||
Dest, CondRes);
|
Dest, CondRes);
|
||||||
}
|
|
||||||
|
|
||||||
SDValue MipsTargetLowering::
|
|
||||||
LowerSETCC(SDValue Op, SelectionDAG &DAG) const
|
|
||||||
{
|
|
||||||
// The operands to this are the left and right operands to compare (ops #0,
|
|
||||||
// and #1) and the condition code to compare them with (op #2) as a
|
|
||||||
// CondCodeSDNode.
|
|
||||||
SDValue LHS = Op.getOperand(0);
|
|
||||||
SDValue RHS = Op.getOperand(1);
|
|
||||||
DebugLoc dl = Op.getDebugLoc();
|
|
||||||
|
|
||||||
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
|
|
||||||
|
|
||||||
return DAG.getNode(MipsISD::FPCmp, dl, Op.getValueType(), LHS, RHS,
|
|
||||||
DAG.getConstant(FPCondCCodeToFCC(CC), MVT::i32));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue MipsTargetLowering::
|
SDValue MipsTargetLowering::
|
||||||
LowerSELECT(SDValue Op, SelectionDAG &DAG) const
|
LowerSELECT(SDValue Op, SelectionDAG &DAG) const
|
||||||
{
|
{
|
||||||
SDValue Cond = Op.getOperand(0);
|
SDValue Cond = CreateFPCmp(DAG, Op.getOperand(0));
|
||||||
SDValue True = Op.getOperand(1);
|
|
||||||
SDValue False = Op.getOperand(2);
|
|
||||||
DebugLoc dl = Op.getDebugLoc();
|
|
||||||
|
|
||||||
// if the incomming condition comes from a integer compare, the select
|
// Return if flag is not set by a floating point comparision.
|
||||||
// operation must be SelectCC or a conditional move if the subtarget
|
if (Cond.getOpcode() != MipsISD::FPCmp)
|
||||||
// supports it.
|
return Op;
|
||||||
if (Cond.getOpcode() != MipsISD::FPCmp) {
|
|
||||||
if (Subtarget->hasCondMov() && !True.getValueType().isFloatingPoint())
|
|
||||||
return Op;
|
|
||||||
return DAG.getNode(MipsISD::SelectCC, dl, True.getValueType(),
|
|
||||||
Cond, True, False);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the incomming condition comes from fpcmp, the select
|
return CreateCMovFP(DAG, Cond, Op.getOperand(1), Op.getOperand(2),
|
||||||
// operation must use FPSelectCC.
|
Op.getDebugLoc());
|
||||||
SDValue CCNode = Cond.getOperand(2);
|
|
||||||
return DAG.getNode(MipsISD::FPSelectCC, dl, True.getValueType(),
|
|
||||||
Cond, True, False, CCNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op,
|
SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op,
|
||||||
|
@ -40,18 +40,16 @@ namespace llvm {
|
|||||||
// Handle gp_rel (small data/bss sections) relocation.
|
// Handle gp_rel (small data/bss sections) relocation.
|
||||||
GPRel,
|
GPRel,
|
||||||
|
|
||||||
// Select CC Pseudo Instruction
|
|
||||||
SelectCC,
|
|
||||||
|
|
||||||
// Floating Point Select CC Pseudo Instruction
|
|
||||||
FPSelectCC,
|
|
||||||
|
|
||||||
// Floating Point Branch Conditional
|
// Floating Point Branch Conditional
|
||||||
FPBrcond,
|
FPBrcond,
|
||||||
|
|
||||||
// Floating Point Compare
|
// Floating Point Compare
|
||||||
FPCmp,
|
FPCmp,
|
||||||
|
|
||||||
|
// Floating Point Conditional Moves
|
||||||
|
CMovFP_T,
|
||||||
|
CMovFP_F,
|
||||||
|
|
||||||
// Floating Point Rounding
|
// Floating Point Rounding
|
||||||
FPRound,
|
FPRound,
|
||||||
|
|
||||||
@ -105,7 +103,6 @@ namespace llvm {
|
|||||||
SmallVectorImpl<SDValue> &InVals) const;
|
SmallVectorImpl<SDValue> &InVals) const;
|
||||||
|
|
||||||
// Lower Operand specifics
|
// Lower Operand specifics
|
||||||
SDValue LowerANDOR(SDValue Op, SelectionDAG &DAG) const;
|
|
||||||
SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const;
|
||||||
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
|
||||||
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
|
||||||
@ -115,7 +112,6 @@ namespace llvm {
|
|||||||
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
|
||||||
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
|
||||||
SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const;
|
||||||
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
|
|
||||||
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
||||||
|
|
||||||
virtual SDValue
|
virtual SDValue
|
||||||
|
@ -24,19 +24,19 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// Floating Point Compare and Branch
|
// Floating Point Compare and Branch
|
||||||
def SDT_MipsFPBrcond : SDTypeProfile<0, 3, [SDTCisSameAs<0, 2>, SDTCisInt<0>,
|
def SDT_MipsFPBrcond : SDTypeProfile<0, 2, [SDTCisInt<0>,
|
||||||
SDTCisVT<1, OtherVT>]>;
|
SDTCisVT<1, OtherVT>]>;
|
||||||
def SDT_MipsFPCmp : SDTypeProfile<1, 3, [SDTCisVT<0, i32>,
|
def SDT_MipsFPCmp : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>, SDTCisFP<1>,
|
||||||
SDTCisSameAs<1, 2>, SDTCisFP<1>,
|
SDTCisInt<2>]>;
|
||||||
SDTCisInt<3>]>;
|
def SDT_MipsCMovFP : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
|
||||||
def SDT_MipsFPSelectCC : SDTypeProfile<1, 4, [SDTCisInt<1>, SDTCisInt<4>,
|
SDTCisSameAs<1, 2>]>;
|
||||||
SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>]>;
|
|
||||||
|
|
||||||
|
def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp, [SDNPOutGlue]>;
|
||||||
|
def MipsCMovFP_T : SDNode<"MipsISD::CMovFP_T", SDT_MipsCMovFP, [SDNPInGlue]>;
|
||||||
|
def MipsCMovFP_F : SDNode<"MipsISD::CMovFP_F", SDT_MipsCMovFP, [SDNPInGlue]>;
|
||||||
def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInGlue]>;
|
def MipsFPRound : SDNode<"MipsISD::FPRound", SDTFPRoundOp, [SDNPOptInGlue]>;
|
||||||
def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond,
|
def MipsFPBrcond : SDNode<"MipsISD::FPBrcond", SDT_MipsFPBrcond,
|
||||||
[SDNPHasChain]>;
|
[SDNPHasChain, SDNPOptInGlue]>;
|
||||||
def MipsFPCmp : SDNode<"MipsISD::FPCmp", SDT_MipsFPCmp>;
|
|
||||||
def MipsFPSelectCC : SDNode<"MipsISD::FPSelectCC", SDT_MipsFPSelectCC>;
|
|
||||||
|
|
||||||
// Operand for printing out a condition code.
|
// Operand for printing out a condition code.
|
||||||
let PrintMethod = "printFCCOperand" in
|
let PrintMethod = "printFCCOperand" in
|
||||||
@ -210,11 +210,11 @@ def MIPS_BRANCH_FL : PatLeaf<(i32 2)>;
|
|||||||
def MIPS_BRANCH_TL : PatLeaf<(i32 3)>;
|
def MIPS_BRANCH_TL : PatLeaf<(i32 3)>;
|
||||||
|
|
||||||
/// Floating Point Branch of False/True (Likely)
|
/// Floating Point Branch of False/True (Likely)
|
||||||
let isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in {
|
let isBranch=1, isTerminator=1, hasDelaySlot=1, base=0x8, Uses=[FCR31] in
|
||||||
class FBRANCH<PatLeaf op, string asmstr> : FFI<0x11, (outs),
|
class FBRANCH<PatLeaf op, string asmstr> : FFI<0x11, (outs),
|
||||||
(ins brtarget:$dst), !strconcat(asmstr, " $dst"),
|
(ins brtarget:$dst), !strconcat(asmstr, " $dst"),
|
||||||
[(MipsFPBrcond op, bb:$dst, FCR31)]>;
|
[(MipsFPBrcond op, bb:$dst)]>;
|
||||||
}
|
|
||||||
def BC1F : FBRANCH<MIPS_BRANCH_F, "bc1f">;
|
def BC1F : FBRANCH<MIPS_BRANCH_F, "bc1f">;
|
||||||
def BC1T : FBRANCH<MIPS_BRANCH_T, "bc1t">;
|
def BC1T : FBRANCH<MIPS_BRANCH_T, "bc1t">;
|
||||||
def BC1FL : FBRANCH<MIPS_BRANCH_FL, "bc1fl">;
|
def BC1FL : FBRANCH<MIPS_BRANCH_FL, "bc1fl">;
|
||||||
@ -227,7 +227,7 @@ def BC1TL : FBRANCH<MIPS_BRANCH_TL, "bc1tl">;
|
|||||||
// They must be kept in synch.
|
// They must be kept in synch.
|
||||||
def MIPS_FCOND_F : PatLeaf<(i32 0)>;
|
def MIPS_FCOND_F : PatLeaf<(i32 0)>;
|
||||||
def MIPS_FCOND_UN : PatLeaf<(i32 1)>;
|
def MIPS_FCOND_UN : PatLeaf<(i32 1)>;
|
||||||
def MIPS_FCOND_EQ : PatLeaf<(i32 2)>;
|
def MIPS_FCOND_OEQ : PatLeaf<(i32 2)>;
|
||||||
def MIPS_FCOND_UEQ : PatLeaf<(i32 3)>;
|
def MIPS_FCOND_UEQ : PatLeaf<(i32 3)>;
|
||||||
def MIPS_FCOND_OLT : PatLeaf<(i32 4)>;
|
def MIPS_FCOND_OLT : PatLeaf<(i32 4)>;
|
||||||
def MIPS_FCOND_ULT : PatLeaf<(i32 5)>;
|
def MIPS_FCOND_ULT : PatLeaf<(i32 5)>;
|
||||||
@ -245,42 +245,70 @@ def MIPS_FCOND_NGT : PatLeaf<(i32 15)>;
|
|||||||
/// Floating Point Compare
|
/// Floating Point Compare
|
||||||
let hasDelaySlot = 1, Defs=[FCR31] in {
|
let hasDelaySlot = 1, Defs=[FCR31] in {
|
||||||
def FCMP_S32 : FCC<0x0, (outs), (ins FGR32:$fs, FGR32:$ft, condcode:$cc),
|
def FCMP_S32 : FCC<0x0, (outs), (ins FGR32:$fs, FGR32:$ft, condcode:$cc),
|
||||||
"c.$cc.s $fs, $ft",
|
"c.$cc.s $fs, $ft",
|
||||||
[(set FCR31, (MipsFPCmp FGR32:$fs, FGR32:$ft, imm:$cc))]>;
|
[(MipsFPCmp FGR32:$fs, FGR32:$ft, imm:$cc)]>;
|
||||||
|
|
||||||
def FCMP_D32 : FCC<0x1, (outs), (ins AFGR64:$fs, AFGR64:$ft, condcode:$cc),
|
def FCMP_D32 : FCC<0x1, (outs), (ins AFGR64:$fs, AFGR64:$ft, condcode:$cc),
|
||||||
"c.$cc.d $fs, $ft",
|
"c.$cc.d $fs, $ft",
|
||||||
[(set FCR31, (MipsFPCmp AFGR64:$fs, AFGR64:$ft, imm:$cc))]>,
|
[(MipsFPCmp AFGR64:$fs, AFGR64:$ft, imm:$cc)]>,
|
||||||
Requires<[In32BitMode]>;
|
Requires<[In32BitMode]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Conditional moves:
|
||||||
|
// These instructions are expanded in MipsISelLowering::EmitInstrWithCustomInserter
|
||||||
|
// if target does not have conditional move instructions.
|
||||||
|
// flag:int, data:float
|
||||||
|
let usesCustomInserter = 1, Constraints = "$F = $dst" in
|
||||||
|
class CondMovIntFP<RegisterClass RC, bits<5> fmt, bits<6> func,
|
||||||
|
string instr_asm> :
|
||||||
|
FFR<0x11, func, fmt, (outs RC:$dst), (ins RC:$T, CPURegs:$cond, RC:$F),
|
||||||
|
!strconcat(instr_asm, "\t$dst, $T, $cond"), []>;
|
||||||
|
|
||||||
|
def MOVZ_S : CondMovIntFP<FGR32, 16, 18, "movz.s">;
|
||||||
|
def MOVN_S : CondMovIntFP<FGR32, 16, 19, "movn.s">;
|
||||||
|
|
||||||
|
let Predicates = [In32BitMode] in {
|
||||||
|
def MOVZ_D : CondMovIntFP<AFGR64, 17, 18, "movz.d">;
|
||||||
|
def MOVN_D : CondMovIntFP<AFGR64, 17, 19, "movn.d">;
|
||||||
|
}
|
||||||
|
|
||||||
|
defm : MovzPats<FGR32, MOVZ_S>;
|
||||||
|
defm : MovnPats<FGR32, MOVN_S>;
|
||||||
|
|
||||||
|
let Predicates = [In32BitMode] in {
|
||||||
|
defm : MovzPats<AFGR64, MOVZ_D>;
|
||||||
|
defm : MovnPats<AFGR64, MOVN_D>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let usesCustomInserter = 1, Uses = [FCR31], Constraints = "$F = $dst" in {
|
||||||
|
// flag:float, data:int
|
||||||
|
class CondMovFPInt<SDNode cmov, bits<1> tf, string instr_asm> :
|
||||||
|
FCMOV<tf, (outs CPURegs:$dst), (ins CPURegs:$T, CPURegs:$F),
|
||||||
|
!strconcat(instr_asm, "\t$dst, $T, $$fcc0"),
|
||||||
|
[(set CPURegs:$dst, (cmov CPURegs:$T, CPURegs:$F))]>;
|
||||||
|
|
||||||
|
// flag:float, data:float
|
||||||
|
class CondMovFPFP<RegisterClass RC, SDNode cmov, bits<5> fmt, bits<1> tf,
|
||||||
|
string instr_asm> :
|
||||||
|
FFCMOV<fmt, tf, (outs RC:$dst), (ins RC:$T, RC:$F),
|
||||||
|
!strconcat(instr_asm, "\t$dst, $T, $$fcc0"),
|
||||||
|
[(set RC:$dst, (cmov RC:$T, RC:$F))]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
def MOVT : CondMovFPInt<MipsCMovFP_T, 1, "movt">;
|
||||||
|
def MOVF : CondMovFPInt<MipsCMovFP_F, 0, "movf">;
|
||||||
|
def MOVT_S : CondMovFPFP<FGR32, MipsCMovFP_T, 16, 1, "movt.s">;
|
||||||
|
def MOVF_S : CondMovFPFP<FGR32, MipsCMovFP_F, 16, 0, "movf.s">;
|
||||||
|
|
||||||
|
let Predicates = [In32BitMode] in {
|
||||||
|
def MOVT_D : CondMovFPFP<AFGR64, MipsCMovFP_T, 17, 1, "movt.d">;
|
||||||
|
def MOVF_D : CondMovFPFP<AFGR64, MipsCMovFP_F, 17, 0, "movf.d">;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Floating Point Pseudo-Instructions
|
// Floating Point Pseudo-Instructions
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// For some explanation, see Select_CC at MipsInstrInfo.td. We also embedd a
|
|
||||||
// condiciton code to enable easy handling by the Custom Inserter.
|
|
||||||
let usesCustomInserter = 1, Uses=[FCR31] in {
|
|
||||||
class PseudoFPSelCC<RegisterClass RC, string asmstr> :
|
|
||||||
MipsPseudo<(outs RC:$dst),
|
|
||||||
(ins CPURegs:$CmpRes, RC:$T, RC:$F, condcode:$cc), asmstr,
|
|
||||||
[(set RC:$dst, (MipsFPSelectCC CPURegs:$CmpRes, RC:$T, RC:$F,
|
|
||||||
imm:$cc))]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The values to be selected are fp but the condition test is with integers.
|
|
||||||
def Select_CC_S32 : PseudoSelCC<FGR32, "# MipsSelect_CC_S32_f32">;
|
|
||||||
def Select_CC_D32 : PseudoSelCC<AFGR64, "# MipsSelect_CC_D32_f32">,
|
|
||||||
Requires<[In32BitMode]>;
|
|
||||||
|
|
||||||
// The values to be selected are int but the condition test is done with fp.
|
|
||||||
def Select_FCC : PseudoFPSelCC<CPURegs, "# MipsSelect_FCC">;
|
|
||||||
|
|
||||||
// The values to be selected and the condition test is done with fp.
|
|
||||||
def Select_FCC_S32 : PseudoFPSelCC<FGR32, "# MipsSelect_FCC_S32_f32">;
|
|
||||||
def Select_FCC_D32 : PseudoFPSelCC<AFGR64, "# MipsSelect_FCC_D32_f32">,
|
|
||||||
Requires<[In32BitMode]>;
|
|
||||||
|
|
||||||
def MOVCCRToCCR : MipsPseudo<(outs CCR:$dst), (ins CCR:$src),
|
def MOVCCRToCCR : MipsPseudo<(outs CCR:$dst), (ins CCR:$src),
|
||||||
"# MOVCCRToCCR", []>;
|
"# MOVCCRToCCR", []>;
|
||||||
|
|
||||||
|
@ -180,3 +180,48 @@ class FCC<bits<5> _fmt, dag outs, dag ins, string asmstr, list<dag> pattern> :
|
|||||||
let Inst{5-4} = 0b11;
|
let Inst{5-4} = 0b11;
|
||||||
let Inst{3-0} = cc;
|
let Inst{3-0} = cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FCMOV<bits<1> _tf, dag outs, dag ins, string asmstr,
|
||||||
|
list<dag> pattern> :
|
||||||
|
MipsInst<outs, ins, asmstr, pattern, NoItinerary>
|
||||||
|
{
|
||||||
|
bits<5> rd;
|
||||||
|
bits<5> rs;
|
||||||
|
bits<3> N;
|
||||||
|
bits<1> tf;
|
||||||
|
|
||||||
|
let opcode = 0;
|
||||||
|
let tf = _tf;
|
||||||
|
|
||||||
|
let Inst{25-21} = rs;
|
||||||
|
let Inst{20-18} = N;
|
||||||
|
let Inst{17} = 0;
|
||||||
|
let Inst{16} = tf;
|
||||||
|
let Inst{15-11} = rd;
|
||||||
|
let Inst{10-6} = 0;
|
||||||
|
let Inst{5-0} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FFCMOV<bits<5> _fmt, bits<1> _tf, dag outs, dag ins, string asmstr,
|
||||||
|
list<dag> pattern> :
|
||||||
|
MipsInst<outs, ins, asmstr, pattern, NoItinerary>
|
||||||
|
{
|
||||||
|
bits<5> fd;
|
||||||
|
bits<5> fs;
|
||||||
|
bits<3> N;
|
||||||
|
bits<5> fmt;
|
||||||
|
bits<1> tf;
|
||||||
|
|
||||||
|
let opcode = 17;
|
||||||
|
let fmt = _fmt;
|
||||||
|
let tf = _tf;
|
||||||
|
|
||||||
|
let Inst{25-21} = fmt;
|
||||||
|
let Inst{20-18} = N;
|
||||||
|
let Inst{17} = 0;
|
||||||
|
let Inst{16} = tf;
|
||||||
|
let Inst{15-11} = fs;
|
||||||
|
let Inst{10-6} = fd;
|
||||||
|
let Inst{5-0} = 17;
|
||||||
|
}
|
@ -252,7 +252,7 @@ unsigned Mips::GetCondBranchFromCond(Mips::CondCode CC)
|
|||||||
|
|
||||||
case Mips::FCOND_F:
|
case Mips::FCOND_F:
|
||||||
case Mips::FCOND_UN:
|
case Mips::FCOND_UN:
|
||||||
case Mips::FCOND_EQ:
|
case Mips::FCOND_OEQ:
|
||||||
case Mips::FCOND_UEQ:
|
case Mips::FCOND_UEQ:
|
||||||
case Mips::FCOND_OLT:
|
case Mips::FCOND_OLT:
|
||||||
case Mips::FCOND_ULT:
|
case Mips::FCOND_ULT:
|
||||||
@ -269,8 +269,8 @@ unsigned Mips::GetCondBranchFromCond(Mips::CondCode CC)
|
|||||||
|
|
||||||
case Mips::FCOND_T:
|
case Mips::FCOND_T:
|
||||||
case Mips::FCOND_OR:
|
case Mips::FCOND_OR:
|
||||||
case Mips::FCOND_NEQ:
|
case Mips::FCOND_UNE:
|
||||||
case Mips::FCOND_OGL:
|
case Mips::FCOND_ONE:
|
||||||
case Mips::FCOND_UGE:
|
case Mips::FCOND_UGE:
|
||||||
case Mips::FCOND_OGE:
|
case Mips::FCOND_OGE:
|
||||||
case Mips::FCOND_UGT:
|
case Mips::FCOND_UGT:
|
||||||
@ -300,8 +300,8 @@ Mips::CondCode Mips::GetOppositeBranchCondition(Mips::CondCode CC)
|
|||||||
case Mips::COND_LEZ : return Mips::COND_GZ;
|
case Mips::COND_LEZ : return Mips::COND_GZ;
|
||||||
case Mips::FCOND_F : return Mips::FCOND_T;
|
case Mips::FCOND_F : return Mips::FCOND_T;
|
||||||
case Mips::FCOND_UN : return Mips::FCOND_OR;
|
case Mips::FCOND_UN : return Mips::FCOND_OR;
|
||||||
case Mips::FCOND_EQ : return Mips::FCOND_NEQ;
|
case Mips::FCOND_OEQ: return Mips::FCOND_UNE;
|
||||||
case Mips::FCOND_UEQ: return Mips::FCOND_OGL;
|
case Mips::FCOND_UEQ: return Mips::FCOND_ONE;
|
||||||
case Mips::FCOND_OLT: return Mips::FCOND_UGE;
|
case Mips::FCOND_OLT: return Mips::FCOND_UGE;
|
||||||
case Mips::FCOND_ULT: return Mips::FCOND_OGE;
|
case Mips::FCOND_ULT: return Mips::FCOND_OGE;
|
||||||
case Mips::FCOND_OLE: return Mips::FCOND_UGT;
|
case Mips::FCOND_OLE: return Mips::FCOND_UGT;
|
||||||
|
@ -37,7 +37,7 @@ namespace Mips {
|
|||||||
// To be used with float branch True
|
// To be used with float branch True
|
||||||
FCOND_F,
|
FCOND_F,
|
||||||
FCOND_UN,
|
FCOND_UN,
|
||||||
FCOND_EQ,
|
FCOND_OEQ,
|
||||||
FCOND_UEQ,
|
FCOND_UEQ,
|
||||||
FCOND_OLT,
|
FCOND_OLT,
|
||||||
FCOND_ULT,
|
FCOND_ULT,
|
||||||
@ -57,8 +57,8 @@ namespace Mips {
|
|||||||
// above ones, but are used with a branch False;
|
// above ones, but are used with a branch False;
|
||||||
FCOND_T,
|
FCOND_T,
|
||||||
FCOND_OR,
|
FCOND_OR,
|
||||||
FCOND_NEQ,
|
FCOND_UNE,
|
||||||
FCOND_OGL,
|
FCOND_ONE,
|
||||||
FCOND_UGE,
|
FCOND_UGE,
|
||||||
FCOND_OGE,
|
FCOND_OGE,
|
||||||
FCOND_UGT,
|
FCOND_UGT,
|
||||||
@ -98,10 +98,10 @@ namespace Mips {
|
|||||||
case FCOND_T: return "f";
|
case FCOND_T: return "f";
|
||||||
case FCOND_UN:
|
case FCOND_UN:
|
||||||
case FCOND_OR: return "un";
|
case FCOND_OR: return "un";
|
||||||
case FCOND_EQ:
|
case FCOND_OEQ:
|
||||||
case FCOND_NEQ: return "eq";
|
case FCOND_UNE: return "eq";
|
||||||
case FCOND_UEQ:
|
case FCOND_UEQ:
|
||||||
case FCOND_OGL: return "ueq";
|
case FCOND_ONE: return "ueq";
|
||||||
case FCOND_OLT:
|
case FCOND_OLT:
|
||||||
case FCOND_UGE: return "olt";
|
case FCOND_UGE: return "olt";
|
||||||
case FCOND_ULT:
|
case FCOND_ULT:
|
||||||
@ -121,11 +121,11 @@ namespace Mips {
|
|||||||
case FCOND_LT:
|
case FCOND_LT:
|
||||||
case FCOND_NLT: return "lt";
|
case FCOND_NLT: return "lt";
|
||||||
case FCOND_NGE:
|
case FCOND_NGE:
|
||||||
case FCOND_GE: return "ge";
|
case FCOND_GE: return "nge";
|
||||||
case FCOND_LE:
|
case FCOND_LE:
|
||||||
case FCOND_NLE: return "nle";
|
case FCOND_NLE: return "le";
|
||||||
case FCOND_NGT:
|
case FCOND_NGT:
|
||||||
case FCOND_GT: return "gt";
|
case FCOND_GT: return "ngt";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,6 @@ include "MipsInstrFormats.td"
|
|||||||
|
|
||||||
def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
||||||
def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
|
def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
|
||||||
def SDT_MipsSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 2>,
|
|
||||||
SDTCisSameAs<2, 3>, SDTCisInt<1>]>;
|
|
||||||
def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
|
def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
|
||||||
SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>,
|
SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>,
|
||||||
SDTCisInt<4>]>;
|
SDTCisInt<4>]>;
|
||||||
@ -56,9 +54,6 @@ def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeqStart,
|
|||||||
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd,
|
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd,
|
||||||
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
|
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
|
||||||
|
|
||||||
// Select Condition Code
|
|
||||||
def MipsSelectCC : SDNode<"MipsISD::SelectCC", SDT_MipsSelectCC>;
|
|
||||||
|
|
||||||
// MAdd*/MSub* nodes
|
// MAdd*/MSub* nodes
|
||||||
def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub,
|
def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub,
|
||||||
[SDNPOptInGlue, SDNPOutGlue]>;
|
[SDNPOptInGlue, SDNPOutGlue]>;
|
||||||
@ -363,7 +358,7 @@ def REORDER : MipsPseudo<(outs), (ins), ".set\treorder", []>;
|
|||||||
def NOMACRO : MipsPseudo<(outs), (ins), ".set\tnomacro", []>;
|
def NOMACRO : MipsPseudo<(outs), (ins), ".set\tnomacro", []>;
|
||||||
def NOREORDER : MipsPseudo<(outs), (ins), ".set\tnoreorder", []>;
|
def NOREORDER : MipsPseudo<(outs), (ins), ".set\tnoreorder", []>;
|
||||||
|
|
||||||
// These macros are inserted to prevent GAS from complaining
|
// These macros are inserted to prevent GAS from complaining
|
||||||
// when using the AT register.
|
// when using the AT register.
|
||||||
def NOAT : MipsPseudo<(outs), (ins), ".set\tnoat", []>;
|
def NOAT : MipsPseudo<(outs), (ins), ".set\tnoat", []>;
|
||||||
def ATMACRO : MipsPseudo<(outs), (ins), ".set\tat", []>;
|
def ATMACRO : MipsPseudo<(outs), (ins), ".set\tat", []>;
|
||||||
@ -375,18 +370,6 @@ def ATMACRO : MipsPseudo<(outs), (ins), ".set\tat", []>;
|
|||||||
def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>;
|
def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>;
|
||||||
def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), ".cprestore\t$loc\n", []>;
|
def CPRESTORE : MipsPseudo<(outs), (ins uimm16:$loc), ".cprestore\t$loc\n", []>;
|
||||||
|
|
||||||
// The supported Mips ISAs dont have any instruction close to the SELECT_CC
|
|
||||||
// operation. The solution is to create a Mips pseudo SELECT_CC instruction
|
|
||||||
// (MipsSelectCC), use LowerSELECT_CC to generate this instruction and finally
|
|
||||||
// replace it for real supported nodes into EmitInstrWithCustomInserter
|
|
||||||
let usesCustomInserter = 1 in {
|
|
||||||
class PseudoSelCC<RegisterClass RC, string asmstr>:
|
|
||||||
MipsPseudo<(outs RC:$dst), (ins CPURegs:$CmpRes, RC:$T, RC:$F), asmstr,
|
|
||||||
[(set RC:$dst, (MipsSelectCC CPURegs:$CmpRes, RC:$T, RC:$F))]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
def Select_CC : PseudoSelCC<CPURegs, "# MipsSelect_CC_i32">;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Instruction definition
|
// Instruction definition
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -507,10 +490,18 @@ let Predicates = [HasSwap] in {
|
|||||||
def MIPS_CMOV_ZERO : PatLeaf<(i32 0)>;
|
def MIPS_CMOV_ZERO : PatLeaf<(i32 0)>;
|
||||||
def MIPS_CMOV_NZERO : PatLeaf<(i32 1)>;
|
def MIPS_CMOV_NZERO : PatLeaf<(i32 1)>;
|
||||||
|
|
||||||
let Predicates = [HasCondMov], Constraints = "$F = $dst" in {
|
// Conditional moves:
|
||||||
def MOVN : CondMov<0x0a, "movn", MIPS_CMOV_NZERO>;
|
// These instructions are expanded in MipsISelLowering::EmitInstrWithCustomInserter
|
||||||
def MOVZ : CondMov<0x0b, "movz", MIPS_CMOV_ZERO>;
|
// if target does not have conditional move instructions.
|
||||||
}
|
// flag:int, data:int
|
||||||
|
let usesCustomInserter = 1, shamt = 0, Constraints = "$F = $dst" in
|
||||||
|
class CondMovIntInt<bits<6> funct, string instr_asm> :
|
||||||
|
FR<0, funct, (outs CPURegs:$dst),
|
||||||
|
(ins CPURegs:$T, CPURegs:$cond, CPURegs:$F),
|
||||||
|
!strconcat(instr_asm, "\t$dst, $T, $cond"), [], NoItinerary>;
|
||||||
|
|
||||||
|
def MOVZ_I : CondMovIntInt<0x0a, "movz">;
|
||||||
|
def MOVN_I : CondMovIntInt<0x0b, "movn">;
|
||||||
|
|
||||||
/// No operation
|
/// No operation
|
||||||
let addr=0 in
|
let addr=0 in
|
||||||
@ -619,33 +610,43 @@ def : Pat<(brcond CPURegs:$cond, bb:$dst),
|
|||||||
(BNE CPURegs:$cond, ZERO, bb:$dst)>;
|
(BNE CPURegs:$cond, ZERO, bb:$dst)>;
|
||||||
|
|
||||||
// select patterns
|
// select patterns
|
||||||
def : Pat<(select (setge CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
|
multiclass MovzPats<RegisterClass RC, Instruction MOVZInst> {
|
||||||
(MOVZ CPURegs:$F, CPURegs:$T, (SLT CPURegs:$lhs, CPURegs:$rhs))>;
|
def : Pat<(select (setge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
|
||||||
def : Pat<(select (setuge CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
|
(MOVZInst RC:$T, (SLT CPURegs:$lhs, CPURegs:$rhs), RC:$F)>;
|
||||||
(MOVZ CPURegs:$F, CPURegs:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs))>;
|
def : Pat<(select (setuge CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
|
||||||
def : Pat<(select (setge CPURegs:$lhs, immSExt16:$rhs), CPURegs:$T, CPURegs:$F),
|
(MOVZInst RC:$T, (SLTu CPURegs:$lhs, CPURegs:$rhs), RC:$F)>;
|
||||||
(MOVZ CPURegs:$F, CPURegs:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs))>;
|
def : Pat<(select (setge CPURegs:$lhs, immSExt16:$rhs), RC:$T, RC:$F),
|
||||||
def : Pat<(select (setuge CPURegs:$lh, immSExt16:$rh), CPURegs:$T, CPURegs:$F),
|
(MOVZInst RC:$T, (SLTi CPURegs:$lhs, immSExt16:$rhs), RC:$F)>;
|
||||||
(MOVZ CPURegs:$F, CPURegs:$T, (SLTiu CPURegs:$lh, immSExt16:$rh))>;
|
def : Pat<(select (setuge CPURegs:$lh, immSExt16:$rh), RC:$T, RC:$F),
|
||||||
|
(MOVZInst RC:$T, (SLTiu CPURegs:$lh, immSExt16:$rh), RC:$F)>;
|
||||||
|
def : Pat<(select (setle CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
|
||||||
|
(MOVZInst RC:$T, (SLT CPURegs:$rhs, CPURegs:$lhs), RC:$F)>;
|
||||||
|
def : Pat<(select (setule CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
|
||||||
|
(MOVZInst RC:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs), RC:$F)>;
|
||||||
|
def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
|
||||||
|
(MOVZInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>;
|
||||||
|
def : Pat<(select (seteq CPURegs:$lhs, 0), RC:$T, RC:$F),
|
||||||
|
(MOVZInst RC:$T, CPURegs:$lhs, RC:$F)>;
|
||||||
|
}
|
||||||
|
|
||||||
def : Pat<(select (setle CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
|
multiclass MovnPats<RegisterClass RC, Instruction MOVNInst> {
|
||||||
(MOVZ CPURegs:$F, CPURegs:$T, (SLT CPURegs:$rhs, CPURegs:$lhs))>;
|
def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), RC:$T, RC:$F),
|
||||||
def : Pat<(select (setule CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
|
(MOVNInst RC:$T, (XOR CPURegs:$lhs, CPURegs:$rhs), RC:$F)>;
|
||||||
(MOVZ CPURegs:$F, CPURegs:$T, (SLTu CPURegs:$rhs, CPURegs:$lhs))>;
|
def : Pat<(select CPURegs:$cond, RC:$T, RC:$F),
|
||||||
|
(MOVNInst RC:$T, CPURegs:$cond, RC:$F)>;
|
||||||
|
def : Pat<(select (setne CPURegs:$lhs, 0), RC:$T, RC:$F),
|
||||||
|
(MOVNInst RC:$T, CPURegs:$lhs, RC:$F)>;
|
||||||
|
}
|
||||||
|
|
||||||
def : Pat<(select (seteq CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
|
defm : MovzPats<CPURegs, MOVZ_I>;
|
||||||
(MOVZ CPURegs:$F, CPURegs:$T, (XOR CPURegs:$lhs, CPURegs:$rhs))>;
|
defm : MovnPats<CPURegs, MOVN_I>;
|
||||||
def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs), CPURegs:$T, CPURegs:$F),
|
|
||||||
(MOVN CPURegs:$F, CPURegs:$T, (XOR CPURegs:$lhs, CPURegs:$rhs))>;
|
|
||||||
|
|
||||||
def : Pat<(select CPURegs:$cond, CPURegs:$T, CPURegs:$F),
|
|
||||||
(MOVN CPURegs:$F, CPURegs:$T, CPURegs:$cond)>;
|
|
||||||
|
|
||||||
// select patterns with got access
|
// select patterns with got access
|
||||||
def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs),
|
let AddedComplexity = 10 in
|
||||||
(i32 tglobaladdr:$T), CPURegs:$F),
|
def : Pat<(select (setne CPURegs:$lhs, CPURegs:$rhs),
|
||||||
(MOVN CPURegs:$F, (ADDiu GP, tglobaladdr:$T),
|
(i32 tglobaladdr:$T), CPURegs:$F),
|
||||||
(XOR CPURegs:$lhs, CPURegs:$rhs))>;
|
(MOVN_I CPURegs:$F, (ADDiu GP, tglobaladdr:$T),
|
||||||
|
(XOR CPURegs:$lhs, CPURegs:$rhs))>;
|
||||||
|
|
||||||
// setcc patterns
|
// setcc patterns
|
||||||
def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs),
|
def : Pat<(seteq CPURegs:$lhs, CPURegs:$rhs),
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
; RUN: grep {c\\..*\\.s} %t | count 3
|
; RUN: grep {c\\..*\\.s} %t | count 3
|
||||||
; RUN: grep {bc1\[tf\]} %t | count 3
|
; RUN: grep {bc1\[tf\]} %t | count 3
|
||||||
|
|
||||||
|
; FIXME: Disabled because branch instructions are generated where
|
||||||
|
; conditional move instructions are expected.
|
||||||
|
; REQUIRES: disabled
|
||||||
|
|
||||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
|
||||||
target triple = "mipsallegrexel-unknown-psp-elf"
|
target triple = "mipsallegrexel-unknown-psp-elf"
|
||||||
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
; RUN: llc < %s -march=mips | grep {b\[ne\]\[eq\]} | count 1
|
; RUN: llc < %s -march=mips | grep {b\[ne\]\[eq\]} | count 1
|
||||||
|
|
||||||
|
; FIXME: Disabled because branch instructions are generated where
|
||||||
|
; conditional move instructions are expected.
|
||||||
|
; REQUIRES: disabled
|
||||||
|
|
||||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
|
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"
|
||||||
target triple = "mipsallegrexel-unknown-psp-elf"
|
target triple = "mipsallegrexel-unknown-psp-elf"
|
||||||
|
|
||||||
|
@ -9,12 +9,12 @@ entry:
|
|||||||
volatile store i32 0, i32* %c, align 4
|
volatile store i32 0, i32* %c, align 4
|
||||||
%0 = volatile load i32* %a, align 4 ; <i32> [#uses=1]
|
%0 = volatile load i32* %a, align 4 ; <i32> [#uses=1]
|
||||||
%1 = icmp eq i32 %0, 0 ; <i1> [#uses=1]
|
%1 = icmp eq i32 %0, 0 ; <i1> [#uses=1]
|
||||||
; CHECK: addiu $3, $zero, 0
|
; CHECK: addiu $4, $zero, 0
|
||||||
%iftmp.0.0 = select i1 %1, i32 3, i32 0 ; <i32> [#uses=1]
|
%iftmp.0.0 = select i1 %1, i32 3, i32 0 ; <i32> [#uses=1]
|
||||||
%2 = volatile load i32* %c, align 4 ; <i32> [#uses=1]
|
%2 = volatile load i32* %c, align 4 ; <i32> [#uses=1]
|
||||||
%3 = icmp eq i32 %2, 0 ; <i1> [#uses=1]
|
%3 = icmp eq i32 %2, 0 ; <i1> [#uses=1]
|
||||||
; CHECK: addiu $3, $zero, 3
|
; CHECK: addiu $4, $zero, 3
|
||||||
; CHECK: addu $2, $5, $3
|
; CHECK: addu $2, $3, $4
|
||||||
%iftmp.2.0 = select i1 %3, i32 0, i32 5 ; <i32> [#uses=1]
|
%iftmp.2.0 = select i1 %3, i32 0, i32 5 ; <i32> [#uses=1]
|
||||||
%4 = add nsw i32 %iftmp.2.0, %iftmp.0.0 ; <i32> [#uses=1]
|
%4 = add nsw i32 %iftmp.2.0, %iftmp.0.0 ; <i32> [#uses=1]
|
||||||
ret i32 %4
|
ret i32 %4
|
||||||
|
119
test/CodeGen/Mips/fpbr.ll
Normal file
119
test/CodeGen/Mips/fpbr.ll
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
; RUN: llc < %s -march=mipsel | FileCheck %s
|
||||||
|
|
||||||
|
define void @func0(float %f2, float %f3) nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK: c.eq.s
|
||||||
|
; CHECK: bc1f
|
||||||
|
%cmp = fcmp oeq float %f2, %f3
|
||||||
|
br i1 %cmp, label %if.then, label %if.else
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
tail call void (...)* @g0() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.else: ; preds = %entry
|
||||||
|
tail call void (...)* @g1() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.else, %if.then
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @g0(...)
|
||||||
|
|
||||||
|
declare void @g1(...)
|
||||||
|
|
||||||
|
define void @func1(float %f2, float %f3) nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK: c.olt.s
|
||||||
|
; CHECK: bc1f
|
||||||
|
%cmp = fcmp olt float %f2, %f3
|
||||||
|
br i1 %cmp, label %if.then, label %if.else
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
tail call void (...)* @g0() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.else: ; preds = %entry
|
||||||
|
tail call void (...)* @g1() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.else, %if.then
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @func2(float %f2, float %f3) nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK: c.ole.s
|
||||||
|
; CHECK: bc1f
|
||||||
|
%cmp = fcmp ugt float %f2, %f3
|
||||||
|
br i1 %cmp, label %if.else, label %if.then
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
tail call void (...)* @g0() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.else: ; preds = %entry
|
||||||
|
tail call void (...)* @g1() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.else, %if.then
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @func3(double %f2, double %f3) nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK: c.eq.d
|
||||||
|
; CHECK: bc1f
|
||||||
|
%cmp = fcmp oeq double %f2, %f3
|
||||||
|
br i1 %cmp, label %if.then, label %if.else
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
tail call void (...)* @g0() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.else: ; preds = %entry
|
||||||
|
tail call void (...)* @g1() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.else, %if.then
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @func4(double %f2, double %f3) nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK: c.olt.d
|
||||||
|
; CHECK: bc1f
|
||||||
|
%cmp = fcmp olt double %f2, %f3
|
||||||
|
br i1 %cmp, label %if.then, label %if.else
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
tail call void (...)* @g0() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.else: ; preds = %entry
|
||||||
|
tail call void (...)* @g1() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.else, %if.then
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @func5(double %f2, double %f3) nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK: c.ole.d
|
||||||
|
; CHECK: bc1f
|
||||||
|
%cmp = fcmp ugt double %f2, %f3
|
||||||
|
br i1 %cmp, label %if.else, label %if.then
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
tail call void (...)* @g0() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.else: ; preds = %entry
|
||||||
|
tail call void (...)* @g1() nounwind
|
||||||
|
br label %if.end
|
||||||
|
|
||||||
|
if.end: ; preds = %if.else, %if.then
|
||||||
|
ret void
|
||||||
|
}
|
23
test/CodeGen/Mips/fpcmp.ll
Normal file
23
test/CodeGen/Mips/fpcmp.ll
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
; RUN: llc < %s -march=mipsel -mcpu=4ke | FileCheck %s -check-prefix=CHECK-MIPS32R2
|
||||||
|
; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=CHECK-MIPS1
|
||||||
|
|
||||||
|
@g1 = external global i32
|
||||||
|
|
||||||
|
define i32 @f(float %f0, float %f1) nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.olt.s
|
||||||
|
; CHECK-MIPS32R2: movt
|
||||||
|
; CHECK-MIPS32R2: c.olt.s
|
||||||
|
; CHECK-MIPS32R2: movt
|
||||||
|
; CHECK-MIPS1: c.olt.s
|
||||||
|
; CHECK-MIPS1: bc1f
|
||||||
|
; CHECK-MIPS1: c.olt.s
|
||||||
|
; CHECK-MIPS1: bc1f
|
||||||
|
%cmp = fcmp olt float %f0, %f1
|
||||||
|
%conv = zext i1 %cmp to i32
|
||||||
|
%tmp2 = load i32* @g1, align 4
|
||||||
|
%add = add nsw i32 %tmp2, %conv
|
||||||
|
store i32 %add, i32* @g1, align 4
|
||||||
|
%cond = select i1 %cmp, i32 10, i32 20
|
||||||
|
ret i32 %cond
|
||||||
|
}
|
196
test/CodeGen/Mips/select.ll
Normal file
196
test/CodeGen/Mips/select.ll
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
; RUN: llc < %s -march=mipsel -mcpu=4ke | FileCheck %s -check-prefix=CHECK-MIPS32R2
|
||||||
|
; RUN: llc < %s -march=mipsel | FileCheck %s -check-prefix=CHECK-MIPS1
|
||||||
|
|
||||||
|
@d2 = external global double
|
||||||
|
@d3 = external global double
|
||||||
|
|
||||||
|
define i32 @sel1(i32 %s, i32 %f0, i32 %f1) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: movn
|
||||||
|
; CHECK-MIPS1: beq
|
||||||
|
%tobool = icmp ne i32 %s, 0
|
||||||
|
%cond = select i1 %tobool, i32 %f1, i32 %f0
|
||||||
|
ret i32 %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define float @sel2(i32 %s, float %f0, float %f1) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: movn.s
|
||||||
|
; CHECK-MIPS1: beq
|
||||||
|
%tobool = icmp ne i32 %s, 0
|
||||||
|
%cond = select i1 %tobool, float %f0, float %f1
|
||||||
|
ret float %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @sel2_1(i32 %s, double %f0, double %f1) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: movn.d
|
||||||
|
; CHECK-MIPS1: beq
|
||||||
|
%tobool = icmp ne i32 %s, 0
|
||||||
|
%cond = select i1 %tobool, double %f0, double %f1
|
||||||
|
ret double %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define float @sel3(float %f0, float %f1, float %f2, float %f3) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.eq.s
|
||||||
|
; CHECK-MIPS32R2: movt.s
|
||||||
|
; CHECK-MIPS1: c.eq.s
|
||||||
|
; CHECK-MIPS1: bc1f
|
||||||
|
%cmp = fcmp oeq float %f2, %f3
|
||||||
|
%cond = select i1 %cmp, float %f0, float %f1
|
||||||
|
ret float %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define float @sel4(float %f0, float %f1, float %f2, float %f3) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.olt.s
|
||||||
|
; CHECK-MIPS32R2: movt.s
|
||||||
|
; CHECK-MIPS1: c.olt.s
|
||||||
|
; CHECK-MIPS1: bc1f
|
||||||
|
%cmp = fcmp olt float %f2, %f3
|
||||||
|
%cond = select i1 %cmp, float %f0, float %f1
|
||||||
|
ret float %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define float @sel5(float %f0, float %f1, float %f2, float %f3) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.ule.s
|
||||||
|
; CHECK-MIPS32R2: movf.s
|
||||||
|
; CHECK-MIPS1: c.ule.s
|
||||||
|
; CHECK-MIPS1: bc1t
|
||||||
|
%cmp = fcmp ogt float %f2, %f3
|
||||||
|
%cond = select i1 %cmp, float %f0, float %f1
|
||||||
|
ret float %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @sel5_1(double %f0, double %f1, float %f2, float %f3) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.ule.s
|
||||||
|
; CHECK-MIPS32R2: movf.d
|
||||||
|
; CHECK-MIPS1: c.ule.s
|
||||||
|
; CHECK-MIPS1: bc1t
|
||||||
|
%cmp = fcmp ogt float %f2, %f3
|
||||||
|
%cond = select i1 %cmp, double %f0, double %f1
|
||||||
|
ret double %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @sel6(double %f0, double %f1, double %f2, double %f3) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.eq.d
|
||||||
|
; CHECK-MIPS32R2: movt.d
|
||||||
|
; CHECK-MIPS1: c.eq.d
|
||||||
|
; CHECK-MIPS1: bc1f
|
||||||
|
%cmp = fcmp oeq double %f2, %f3
|
||||||
|
%cond = select i1 %cmp, double %f0, double %f1
|
||||||
|
ret double %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @sel7(double %f0, double %f1, double %f2, double %f3) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.olt.d
|
||||||
|
; CHECK-MIPS32R2: movt.d
|
||||||
|
; CHECK-MIPS1: c.olt.d
|
||||||
|
; CHECK-MIPS1: bc1f
|
||||||
|
%cmp = fcmp olt double %f2, %f3
|
||||||
|
%cond = select i1 %cmp, double %f0, double %f1
|
||||||
|
ret double %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define double @sel8(double %f0, double %f1, double %f2, double %f3) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.ule.d
|
||||||
|
; CHECK-MIPS32R2: movf.d
|
||||||
|
; CHECK-MIPS1: c.ule.d
|
||||||
|
; CHECK-MIPS1: bc1t
|
||||||
|
%cmp = fcmp ogt double %f2, %f3
|
||||||
|
%cond = select i1 %cmp, double %f0, double %f1
|
||||||
|
ret double %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define float @sel8_1(float %f0, float %f1, double %f2, double %f3) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.ule.d
|
||||||
|
; CHECK-MIPS32R2: movf.s
|
||||||
|
; CHECK-MIPS1: c.ule.d
|
||||||
|
; CHECK-MIPS1: bc1t
|
||||||
|
%cmp = fcmp ogt double %f2, %f3
|
||||||
|
%cond = select i1 %cmp, float %f0, float %f1
|
||||||
|
ret float %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @sel9(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.eq.s
|
||||||
|
; CHECK-MIPS32R2: movt
|
||||||
|
; CHECK-MIPS1: c.eq.s
|
||||||
|
; CHECK-MIPS1: bc1f
|
||||||
|
%cmp = fcmp oeq float %f2, %f3
|
||||||
|
%cond = select i1 %cmp, i32 %f0, i32 %f1
|
||||||
|
ret i32 %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @sel10(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.olt.s
|
||||||
|
; CHECK-MIPS32R2: movt
|
||||||
|
; CHECK-MIPS1: c.olt.s
|
||||||
|
; CHECK-MIPS1: bc1f
|
||||||
|
%cmp = fcmp olt float %f2, %f3
|
||||||
|
%cond = select i1 %cmp, i32 %f0, i32 %f1
|
||||||
|
ret i32 %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @sel11(i32 %f0, i32 %f1, float %f2, float %f3) nounwind readnone {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.ule.s
|
||||||
|
; CHECK-MIPS32R2: movf
|
||||||
|
; CHECK-MIPS1: c.ule.s
|
||||||
|
; CHECK-MIPS1: bc1t
|
||||||
|
%cmp = fcmp ogt float %f2, %f3
|
||||||
|
%cond = select i1 %cmp, i32 %f0, i32 %f1
|
||||||
|
ret i32 %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @sel12(i32 %f0, i32 %f1) nounwind readonly {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.eq.d
|
||||||
|
; CHECK-MIPS32R2: movt
|
||||||
|
; CHECK-MIPS1: c.eq.d
|
||||||
|
; CHECK-MIPS1: bc1f
|
||||||
|
%tmp = load double* @d2, align 8, !tbaa !0
|
||||||
|
%tmp1 = load double* @d3, align 8, !tbaa !0
|
||||||
|
%cmp = fcmp oeq double %tmp, %tmp1
|
||||||
|
%cond = select i1 %cmp, i32 %f0, i32 %f1
|
||||||
|
ret i32 %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @sel13(i32 %f0, i32 %f1) nounwind readonly {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.olt.d
|
||||||
|
; CHECK-MIPS32R2: movt
|
||||||
|
; CHECK-MIPS1: c.olt.d
|
||||||
|
; CHECK-MIPS1: bc1f
|
||||||
|
%tmp = load double* @d2, align 8, !tbaa !0
|
||||||
|
%tmp1 = load double* @d3, align 8, !tbaa !0
|
||||||
|
%cmp = fcmp olt double %tmp, %tmp1
|
||||||
|
%cond = select i1 %cmp, i32 %f0, i32 %f1
|
||||||
|
ret i32 %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @sel14(i32 %f0, i32 %f1) nounwind readonly {
|
||||||
|
entry:
|
||||||
|
; CHECK-MIPS32R2: c.ule.d
|
||||||
|
; CHECK-MIPS32R2: movf
|
||||||
|
; CHECK-MIPS1: c.ule.d
|
||||||
|
; CHECK-MIPS1: bc1t
|
||||||
|
%tmp = load double* @d2, align 8, !tbaa !0
|
||||||
|
%tmp1 = load double* @d3, align 8, !tbaa !0
|
||||||
|
%cmp = fcmp ogt double %tmp, %tmp1
|
||||||
|
%cond = select i1 %cmp, i32 %f0, i32 %f1
|
||||||
|
ret i32 %cond
|
||||||
|
}
|
||||||
|
|
||||||
|
!0 = metadata !{metadata !"double", metadata !1}
|
||||||
|
!1 = metadata !{metadata !"omnipotent char", metadata !2}
|
||||||
|
!2 = metadata !{metadata !"Simple C/C++ TBAA", null}
|
Loading…
Reference in New Issue
Block a user