diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 224569b2503..1d7a1c0ae8c 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -179,11 +179,11 @@ unsigned MipsTargetLowering::getFunctionAlignment(const Function *) const { // (addc multLo, Lo0), (adde multHi, Hi0), // where, // multHi/Lo: product of multiplication -// Lo0: initial value of Lo register -// Hi0: initial value of Hi register +// Lo0: initial value of Lo register +// Hi0: initial value of Hi register // Return true if mattern matching was successful. static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { - // ADDENode's second operand must be a flag output of an ADDC node in order + // ADDENode's second operand must be a flag output of an ADDC node in order // for the matching to be successful. SDNode* ADDCNode = ADDENode->getOperand(2).getNode(); @@ -192,7 +192,7 @@ static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { SDValue MultHi = ADDENode->getOperand(0); SDValue MultLo = ADDCNode->getOperand(0); - SDNode* MultNode = MultHi.getNode(); + SDNode* MultNode = MultHi.getNode(); unsigned MultOpc = MultHi.getOpcode(); // MultHi and MultLo must be generated by the same node, @@ -202,39 +202,39 @@ static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { // and it must be a multiplication. if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI) return false; - - // MultLo amd MultHi must be the first and second output of MultNode - // respectively. + + // MultLo amd MultHi must be the first and second output of MultNode + // respectively. if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0) return false; - // Transform this to a MADD only if ADDENode and ADDCNode are the only users + // Transform this to a MADD only if ADDENode and ADDCNode are the only users // of the values of MultNode, in which case MultNode will be removed in later // phases. // If there exist users other than ADDENode or ADDCNode, this function returns - // here, which will result in MultNode being mapped to a single MULT - // instruction node rather than a pair of MULT and MADD instructions being + // here, which will result in MultNode being mapped to a single MULT + // instruction node rather than a pair of MULT and MADD instructions being // produced. if (!MultHi.hasOneUse() || !MultLo.hasOneUse()) return false; - SDValue Chain = CurDAG->getEntryNode(); + SDValue Chain = CurDAG->getEntryNode(); DebugLoc dl = ADDENode->getDebugLoc(); // create MipsMAdd(u) node MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd; - + SDValue MAdd = CurDAG->getNode(MultOpc, dl, MVT::Glue, MultNode->getOperand(0),// Factor 0 MultNode->getOperand(1),// Factor 1 - ADDCNode->getOperand(1),// Lo0 + ADDCNode->getOperand(1),// Lo0 ADDENode->getOperand(1));// Hi0 // create CopyFromReg nodes SDValue CopyFromLo = CurDAG->getCopyFromReg(Chain, dl, Mips::LO, MVT::i32, MAdd); - SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), dl, + SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), dl, Mips::HI, MVT::i32, CopyFromLo.getValue(2)); @@ -245,7 +245,7 @@ static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { if (!SDValue(ADDENode, 0).use_empty()) CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), CopyFromHi); - return true; + return true; } // SelectMsub - @@ -253,11 +253,11 @@ static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) { // (addc Lo0, multLo), (sube Hi0, multHi), // where, // multHi/Lo: product of multiplication -// Lo0: initial value of Lo register -// Hi0: initial value of Hi register +// Lo0: initial value of Lo register +// Hi0: initial value of Hi register // Return true if mattern matching was successful. static bool SelectMsub(SDNode* SUBENode, SelectionDAG* CurDAG) { - // SUBENode's second operand must be a flag output of an SUBC node in order + // SUBENode's second operand must be a flag output of an SUBC node in order // for the matching to be successful. SDNode* SUBCNode = SUBENode->getOperand(2).getNode(); @@ -266,7 +266,7 @@ static bool SelectMsub(SDNode* SUBENode, SelectionDAG* CurDAG) { SDValue MultHi = SUBENode->getOperand(1); SDValue MultLo = SUBCNode->getOperand(1); - SDNode* MultNode = MultHi.getNode(); + SDNode* MultNode = MultHi.getNode(); unsigned MultOpc = MultHi.getOpcode(); // MultHi and MultLo must be generated by the same node, @@ -330,9 +330,9 @@ static SDValue PerformADDECombine(SDNode *N, SelectionDAG& DAG, if (Subtarget->isMips32() && SelectMadd(N, &DAG)) return SDValue(N, 0); - + return SDValue(); -} +} static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG, TargetLowering::DAGCombinerInfo &DCI, @@ -342,11 +342,11 @@ static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG, if (Subtarget->isMips32() && SelectMsub(N, &DAG)) return SDValue(N, 0); - - return SDValue(); -} -SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) + return SDValue(); +} + +SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; unsigned opc = N->getOpcode(); @@ -842,9 +842,15 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, Mips::D6, Mips::D7 }; - unsigned Reg=0; - unsigned UnallocIntReg = State.getFirstUnallocated(IntRegs, IntRegsSize); - bool IntRegUsed = (IntRegs[UnallocIntReg] != (unsigned (Mips::A0))); + unsigned Reg = 0; + static bool IntRegUsed = false; + + // This must be the first arg of the call if no regs have been allocated. + // Initialize IntRegUsed in that case. + if (IntRegs[State.getFirstUnallocated(IntRegs, IntRegsSize)] == Mips::A0 && + F32Regs[State.getFirstUnallocated(F32Regs, FloatRegsSize)] == Mips::F12 && + F64Regs[State.getFirstUnallocated(F64Regs, FloatRegsSize)] == Mips::D6) + IntRegUsed = false; // Promote i8 and i16 if (LocVT == MVT::i8 || LocVT == MVT::i16) { @@ -857,30 +863,48 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, LocInfo = CCValAssign::AExt; } - if (ValVT == MVT::i32 || (ValVT == MVT::f32 && IntRegUsed)) { + if (ValVT == MVT::i32) { Reg = State.AllocateReg(IntRegs, IntRegsSize); IntRegUsed = true; - LocVT = MVT::i32; - } + } else if (ValVT == MVT::f32) { + // An int reg has to be marked allocated regardless of whether or not + // IntRegUsed is true. + Reg = State.AllocateReg(IntRegs, IntRegsSize); - if (ValVT.isFloatingPoint() && !IntRegUsed) { - if (ValVT == MVT::f32) - Reg = State.AllocateReg(F32Regs, FloatRegsSize); - else - Reg = State.AllocateReg(F64Regs, FloatRegsSize); - } - - if (ValVT == MVT::f64 && IntRegUsed) { - if (UnallocIntReg != IntRegsSize) { - // If we hit register A3 as the first not allocated, we must - // mark it as allocated (shadow) and use the stack instead. - if (IntRegs[UnallocIntReg] != (unsigned (Mips::A3))) - Reg = Mips::A2; - for (;UnallocIntReg < IntRegsSize; ++UnallocIntReg) - State.AllocateReg(UnallocIntReg); + if (IntRegUsed) { + if (Reg) // Int reg is available + LocVT = MVT::i32; + } else { + unsigned FReg = State.AllocateReg(F32Regs, FloatRegsSize); + if (FReg) // F32 reg is available + Reg = FReg; + else if (Reg) // No F32 regs are available, but an int reg is available. + LocVT = MVT::i32; } - LocVT = MVT::i32; - } + } else if (ValVT == MVT::f64) { + // Int regs have to be marked allocated regardless of whether or not + // IntRegUsed is true. + Reg = State.AllocateReg(IntRegs, IntRegsSize); + if (Reg == Mips::A1) + Reg = State.AllocateReg(IntRegs, IntRegsSize); + else if (Reg == Mips::A3) + Reg = 0; + State.AllocateReg(IntRegs, IntRegsSize); + + // At this point, Reg is A0, A2 or 0, and all the unavailable integer regs + // are marked as allocated. + if (IntRegUsed) { + if (Reg)// if int reg is available + LocVT = MVT::i32; + } else { + unsigned FReg = State.AllocateReg(F64Regs, FloatRegsSize); + if (FReg) // F64 reg is available. + Reg = FReg; + else if (Reg) // No F64 regs are available, but an int reg is available. + LocVT = MVT::i32; + } + } else + assert(false && "cannot handle this ValVT"); if (!Reg) { unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; diff --git a/test/CodeGen/Mips/o32-cc.ll b/test/CodeGen/Mips/o32-cc.ll new file mode 100644 index 00000000000..3fd97ce729a --- /dev/null +++ b/test/CodeGen/Mips/o32-cc.ll @@ -0,0 +1,321 @@ +; RUN: llc -march=mips -mcpu=4ke < %s | FileCheck %s + +; $f12, $f14 +; CHECK: ldc1 $f12, %lo($CPI0_0)($2) +; CHECK: ldc1 $f14, %lo($CPI0_1)($3) +define void @testlowercall0() nounwind { +entry: + tail call void @f0(double 5.000000e+00, double 6.000000e+00) nounwind + ret void +} + +declare void @f0(double, double) + +; $f12, $f14 +; CHECK: lwc1 $f12, %lo($CPI1_0)($2) +; CHECK: lwc1 $f14, %lo($CPI1_1)($3) +define void @testlowercall1() nounwind { +entry: + tail call void @f1(float 8.000000e+00, float 9.000000e+00) nounwind + ret void +} + +declare void @f1(float, float) + +; $f12, $f14 +; CHECK: lwc1 $f12, %lo($CPI2_0)($2) +; CHECK: ldc1 $f14, %lo($CPI2_1)($3) +define void @testlowercall2() nounwind { +entry: + tail call void @f2(float 8.000000e+00, double 6.000000e+00) nounwind + ret void +} + +declare void @f2(float, double) + +; $f12, $f14 +; CHECK: ldc1 $f12, %lo($CPI3_0)($2) +; CHECK: lwc1 $f14, %lo($CPI3_1)($3) +define void @testlowercall3() nounwind { +entry: + tail call void @f3(double 5.000000e+00, float 9.000000e+00) nounwind + ret void +} + +declare void @f3(double, float) + +; $4, $5, $6, $7 +; CHECK: addiu $4, $zero, 12 +; CHECK: addiu $5, $zero, 13 +; CHECK: addiu $6, $zero, 14 +; CHECK: addiu $7, $zero, 15 +define void @testlowercall4() nounwind { +entry: + tail call void @f4(i32 12, i32 13, i32 14, i32 15) nounwind + ret void +} + +declare void @f4(i32, i32, i32, i32) + +; $f12, $6, stack +; CHECK: sw $2, 16($sp) +; CHECK: sw $zero, 20($sp) +; CHECK: ldc1 $f12, %lo($CPI5_0)($3) +; CHECK: addiu $6, $zero, 23 +define void @testlowercall5() nounwind { +entry: + tail call void @f5(double 1.500000e+01, i32 23, double 1.700000e+01) nounwind + ret void +} + +declare void @f5(double, i32, double) + +; $f12, $6, $7 +; CHECK: ldc1 $f12, %lo($CPI6_0)($2) +; CHECK: addiu $6, $zero, 33 +; CHECK: addiu $7, $zero, 24 +define void @testlowercall6() nounwind { +entry: + tail call void @f6(double 2.500000e+01, i32 33, i32 24) nounwind + ret void +} + +declare void @f6(double, i32, i32) + +; $f12, $5, $6 +; CHECK: lwc1 $f12, %lo($CPI7_0)($2) +; CHECK: addiu $5, $zero, 43 +; CHECK: addiu $6, $zero, 34 +define void @testlowercall7() nounwind { +entry: + tail call void @f7(float 1.800000e+01, i32 43, i32 34) nounwind + ret void +} + +declare void @f7(float, i32, i32) + +; $4, $5, $6, stack +; CHECK: sw $2, 16($sp) +; CHECK: sw $zero, 20($sp) +; CHECK: addiu $4, $zero, 22 +; CHECK: addiu $5, $zero, 53 +; CHECK: addiu $6, $zero, 44 +define void @testlowercall8() nounwind { +entry: + tail call void @f8(i32 22, i32 53, i32 44, double 4.000000e+00) nounwind + ret void +} + +declare void @f8(i32, i32, i32, double) + +; $4, $5, $6, $7 +; CHECK: addiu $4, $zero, 32 +; CHECK: addiu $5, $zero, 63 +; CHECK: addiu $6, $zero, 54 +; CHECK: ori $7, $2, 0 +define void @testlowercall9() nounwind { +entry: + tail call void @f9(i32 32, i32 63, i32 54, float 1.100000e+01) nounwind + ret void +} + +declare void @f9(i32, i32, i32, float) + +; $4, $5, ($6, $7) +; CHECK: addiu $4, $zero, 42 +; CHECK: addiu $5, $zero, 73 +; CHECK: addiu $6, $zero, 0 +; CHECK: ori $7, $2, 0 +define void @testlowercall10() nounwind { +entry: + tail call void @f10(i32 42, i32 73, double 2.700000e+01) nounwind + ret void +} + +declare void @f10(i32, i32, double) + +; $4, ($6, $7) +; CHECK: addiu $4, $zero, 52 +; CHECK: addiu $6, $zero, 0 +; CHECK: ori $7, $2, 0 +define void @testlowercall11() nounwind { +entry: + tail call void @f11(i32 52, double 1.600000e+01) nounwind + ret void +} + +declare void @f11(i32, double) + +; $f12, $f14, $6, $7 +; CHECK: lwc1 $f12, %lo($CPI12_0)($2) +; CHECK: lwc1 $f14, %lo($CPI12_1)($3) +; CHECK: ori $6, $4, 0 +; CHECK: ori $7, $5, 0 +define void @testlowercall12() nounwind { +entry: + tail call void @f12(float 2.800000e+01, float 1.900000e+01, float 1.000000e+01, float 2.100000e+01) nounwind + ret void +} + +declare void @f12(float, float, float, float) + +; $f12, $5, $6, $7 +; CHECK: lwc1 $f12, %lo($CPI13_0)($2) +; CHECK: addiu $5, $zero, 83 +; CHECK: ori $6, $3, 0 +; CHECK: addiu $7, $zero, 25 +define void @testlowercall13() nounwind { +entry: + tail call void @f13(float 3.800000e+01, i32 83, float 2.000000e+01, i32 25) nounwind + ret void +} + + +declare void @f13(float, i32, float, i32) + +; $f12, $f14, $7 +; CHECK: ldc1 $f12, %lo($CPI14_0)($2) +; CHECK: lwc1 $f14, %lo($CPI14_1)($3) +; CHECK: ori $7, $4, 0 +define void @testlowercall14() nounwind { +entry: + tail call void @f14(double 3.500000e+01, float 2.900000e+01, float 3.000000e+01) nounwind + ret void +} + +declare void @f14(double, float, float) + +; $f12, $f14, ($6, $7) +; CHECK: lwc1 $f12, %lo($CPI15_0)($2) +; CHECK: lwc1 $f14, %lo($CPI15_1)($3) +; CHECK: addiu $6, $zero, 0 +; CHECK: ori $7, $4, 32768 +define void @testlowercall15() nounwind { +entry: + tail call void @f15(float 4.800000e+01, float 3.900000e+01, double 3.700000e+01) nounwind + ret void +} + +declare void @f15(float, float, double) + +; $4, $5, $6, $7 +; CHECK: addiu $4, $zero, 62 +; CHECK: ori $5, $2, 0 +; CHECK: addiu $6, $zero, 64 +; CHECK: ori $7, $3, 0 +define void @testlowercall16() nounwind { +entry: + tail call void @f16(i32 62, float 4.900000e+01, i32 64, float 3.100000e+01) nounwind + ret void +} + +declare void @f16(i32, float, i32, float) + +; $4, $5, $6, $7 +; CHECK: addiu $4, $zero, 72 +; CHECK: ori $5, $2, 0 +; CHECK: addiu $6, $zero, 74 +; CHECK: addiu $7, $zero, 35 +define void @testlowercall17() nounwind { +entry: + tail call void @f17(i32 72, float 5.900000e+01, i32 74, i32 35) nounwind + ret void +} + +declare void @f17(i32, float, i32, i32) + +; $4, $5, $6, $7 +; CHECK: addiu $4, $zero, 82 +; CHECK: addiu $5, $zero, 93 +; CHECK: ori $6, $2, 0 +; CHECK: addiu $7, $zero, 45 +define void @testlowercall18() nounwind { +entry: + tail call void @f18(i32 82, i32 93, float 4.000000e+01, i32 45) nounwind + ret void +} + +declare void @f18(i32, i32, float, i32) + + +; $4, ($6, $7), stack +; CHECK: sw $2, 16($sp) +; CHECK: sw $zero, 20($sp) +; CHECK: addiu $4, $zero, 92 +; CHECK: addiu $6, $zero, 0 +; CHECK: ori $7, $3, 0 +define void @testlowercall20() nounwind { +entry: + tail call void @f20(i32 92, double 2.600000e+01, double 4.700000e+01) nounwind + ret void +} + +declare void @f20(i32, double, double) + +; $f12, $5 +; CHECK: lwc1 $f12, %lo($CPI20_0)($2) +; CHECK: addiu $5, $zero, 103 +define void @testlowercall21() nounwind { +entry: + tail call void @f21(float 5.800000e+01, i32 103) nounwind + ret void +} + +declare void @f21(float, i32) + +; $f12, $5, ($6, $7) +; CHECK: lwc1 $f12, %lo($CPI21_0)($2) +; CHECK: addiu $5, $zero, 113 +; CHECK: addiu $6, $zero, 0 +; CHECK: ori $7, $3, 32768 +define void @testlowercall22() nounwind { +entry: + tail call void @f22(float 6.800000e+01, i32 113, double 5.700000e+01) nounwind + ret void +} + +declare void @f22(float, i32, double) + +; $f12, f6 +; CHECK: ldc1 $f12, %lo($CPI22_0)($2) +; CHECK: addiu $6, $zero, 123 +define void @testlowercall23() nounwind { +entry: + tail call void @f23(double 4.500000e+01, i32 123) nounwind + ret void +} + +declare void @f23(double, i32) + +; $f12,$6, stack +; CHECK: sw $2, 16($sp) +; CHECK: sw $zero, 20($sp) +; CHECK: ldc1 $f12, %lo($CPI23_0)($3) +; CHECK: addiu $6, $zero, 133 +define void @testlowercall24() nounwind { +entry: + tail call void @f24(double 5.500000e+01, i32 133, double 6.700000e+01) nounwind + ret void +} + +declare void @f24(double, i32, double) + +; CHECK: lwc1 $f12, %lo($CPI24_0)($2) +; CHECK: lwc1 $f14, %lo($CPI24_1)($3) +; CHECK: ori $6, $4, 0 +; CHECK: ori $7, $5, 0 +; CHECK: lwc1 $f12, %lo($CPI24_2)($2) +; CHECK: addiu $5, $zero, 83 +; CHECK: ori $6, $3, 0 +; CHECK: addiu $7, $zero, 25 +; CHECK: addiu $4, $zero, 82 +; CHECK: addiu $5, $zero, 93 +; CHECK: ori $6, $2, 0 +; CHECK: addiu $7, $zero, 45 +define void @testlowercall25() nounwind { +entry: + tail call void @f12(float 2.800000e+01, float 1.900000e+01, float 1.000000e+01, float 2.100000e+01) nounwind + tail call void @f13(float 3.800000e+01, i32 83, float 2.000000e+01, i32 25) nounwind + tail call void @f18(i32 82, i32 93, float 4.000000e+01, i32 45) nounwind + ret void +}