diff options
Diffstat (limited to 'llvm/lib/Target/M68k/M68kISelLowering.cpp')
| -rw-r--r-- | llvm/lib/Target/M68k/M68kISelLowering.cpp | 243 |
1 files changed, 118 insertions, 125 deletions
diff --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp index 0830cc7feb22..c4d7a0dec7f3 100644 --- a/llvm/lib/Target/M68k/M68kISelLowering.cpp +++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp @@ -94,11 +94,10 @@ M68kTargetLowering::M68kTargetLowering(const M68kTargetMachine &TM, setOperationAction(OP, MVT::i16, Expand); } - // FIXME It would be better to use a custom lowering for (auto OP : {ISD::SMULO, ISD::UMULO}) { - setOperationAction(OP, MVT::i8, Expand); - setOperationAction(OP, MVT::i16, Expand); - setOperationAction(OP, MVT::i32, Expand); + setOperationAction(OP, MVT::i8, Custom); + setOperationAction(OP, MVT::i16, Custom); + setOperationAction(OP, MVT::i32, Custom); } for (auto OP : {ISD::SHL_PARTS, ISD::SRA_PARTS, ISD::SRL_PARTS}) @@ -1533,46 +1532,119 @@ bool M68kTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT, return VT.bitsLE(MVT::i32) || Subtarget.atLeastM68020(); } -SDValue M68kTargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const { - // Lower the "add/sub/mul with overflow" instruction into a regular ins plus - // a "setcc" instruction that checks the overflow flag. The "brcond" lowering - // looks for this combo and may remove the "setcc" instruction if the "setcc" - // has only one use. +static bool isOverflowArithmetic(unsigned Opcode) { + switch (Opcode) { + case ISD::UADDO: + case ISD::SADDO: + case ISD::USUBO: + case ISD::SSUBO: + case ISD::UMULO: + case ISD::SMULO: + return true; + default: + return false; + } +} + +static void lowerOverflowArithmetic(SDValue Op, SelectionDAG &DAG, + SDValue &Result, SDValue &CCR, + unsigned &CC) { SDNode *N = Op.getNode(); + EVT VT = N->getValueType(0); SDValue LHS = N->getOperand(0); SDValue RHS = N->getOperand(1); - unsigned BaseOp = 0; - unsigned Cond = 0; SDLoc DL(Op); + + unsigned TruncOp = 0; + auto PromoteMULO = [&](unsigned ExtOp) { + // We don't have 8-bit multiplications, so promote i8 version of U/SMULO + // to i16. + // Ideally this should be done by legalizer but sadly there is no promotion + // rule for U/SMULO at this moment. + if (VT == MVT::i8) { + LHS = DAG.getNode(ExtOp, DL, MVT::i16, LHS); + RHS = DAG.getNode(ExtOp, DL, MVT::i16, RHS); + VT = MVT::i16; + TruncOp = ISD::TRUNCATE; + } + }; + + bool NoOverflow = false; + unsigned BaseOp = 0; switch (Op.getOpcode()) { default: llvm_unreachable("Unknown ovf instruction!"); case ISD::SADDO: BaseOp = M68kISD::ADD; - Cond = M68k::COND_VS; + CC = M68k::COND_VS; break; case ISD::UADDO: BaseOp = M68kISD::ADD; - Cond = M68k::COND_CS; + CC = M68k::COND_CS; break; case ISD::SSUBO: BaseOp = M68kISD::SUB; - Cond = M68k::COND_VS; + CC = M68k::COND_VS; break; case ISD::USUBO: BaseOp = M68kISD::SUB; - Cond = M68k::COND_CS; + CC = M68k::COND_CS; + break; + case ISD::UMULO: + PromoteMULO(ISD::ZERO_EXTEND); + NoOverflow = VT != MVT::i32; + BaseOp = NoOverflow ? ISD::MUL : M68kISD::UMUL; + CC = M68k::COND_VS; + break; + case ISD::SMULO: + PromoteMULO(ISD::SIGN_EXTEND); + NoOverflow = VT != MVT::i32; + BaseOp = NoOverflow ? ISD::MUL : M68kISD::SMUL; + CC = M68k::COND_VS; break; } - // Also sets CCR. - SDVTList VTs = DAG.getVTList(N->getValueType(0), MVT::i8); + SDVTList VTs; + if (NoOverflow) + VTs = DAG.getVTList(VT); + else + // Also sets CCR. + VTs = DAG.getVTList(VT, MVT::i8); + SDValue Arith = DAG.getNode(BaseOp, DL, VTs, LHS, RHS); - SDValue SetCC = DAG.getNode(M68kISD::SETCC, DL, N->getValueType(1), - DAG.getConstant(Cond, DL, MVT::i8), - SDValue(Arith.getNode(), 1)); + Result = Arith.getValue(0); + if (TruncOp) + // Right now the only place to truncate is from i16 to i8. + Result = DAG.getNode(TruncOp, DL, MVT::i8, Arith); + + if (NoOverflow) + CCR = DAG.getConstant(0, DL, N->getValueType(1)); + else + CCR = Arith.getValue(1); +} + +SDValue M68kTargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const { + SDNode *N = Op.getNode(); + SDLoc DL(Op); + + // Lower the "add/sub/mul with overflow" instruction into a regular ins plus + // a "setcc" instruction that checks the overflow flag. + SDValue Result, CCR; + unsigned CC; + lowerOverflowArithmetic(Op, DAG, Result, CCR, CC); - return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Arith, SetCC); + SDValue Overflow; + if (isa<ConstantSDNode>(CCR)) { + // It's likely a result of operations that will not overflow + // hence no setcc is needed. + Overflow = CCR; + } else { + // Generate a M68kISD::SETCC. + Overflow = DAG.getNode(M68kISD::SETCC, DL, N->getValueType(1), + DAG.getConstant(CC, DL, MVT::i8), CCR); + } + + return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Result, Overflow); } /// Create a BTST (Bit Test) node - Test bit \p BitNo in \p Src and set @@ -2206,8 +2278,7 @@ SDValue M68kTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { isNullConstant(Cond.getOperand(1).getOperand(0))) { SDValue Cmp = Cond.getOperand(1); - unsigned CondCode = - cast<ConstantSDNode>(Cond.getOperand(0))->getZExtValue(); + unsigned CondCode = Cond.getConstantOperandVal(0); if ((isAllOnesConstant(Op1) || isAllOnesConstant(Op2)) && (CondCode == M68k::COND_EQ || CondCode == M68k::COND_NE)) { @@ -2269,55 +2340,12 @@ SDValue M68kTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { Cond = Cmp; addTest = false; } - } else if (CondOpcode == ISD::USUBO || CondOpcode == ISD::SSUBO || - CondOpcode == ISD::UADDO || CondOpcode == ISD::SADDO || - CondOpcode == ISD::UMULO || CondOpcode == ISD::SMULO) { - SDValue LHS = Cond.getOperand(0); - SDValue RHS = Cond.getOperand(1); - unsigned MxOpcode; - unsigned MxCond; - SDVTList VTs; - switch (CondOpcode) { - case ISD::UADDO: - MxOpcode = M68kISD::ADD; - MxCond = M68k::COND_CS; - break; - case ISD::SADDO: - MxOpcode = M68kISD::ADD; - MxCond = M68k::COND_VS; - break; - case ISD::USUBO: - MxOpcode = M68kISD::SUB; - MxCond = M68k::COND_CS; - break; - case ISD::SSUBO: - MxOpcode = M68kISD::SUB; - MxCond = M68k::COND_VS; - break; - case ISD::UMULO: - MxOpcode = M68kISD::UMUL; - MxCond = M68k::COND_VS; - break; - case ISD::SMULO: - MxOpcode = M68kISD::SMUL; - MxCond = M68k::COND_VS; - break; - default: - llvm_unreachable("unexpected overflowing operator"); - } - if (CondOpcode == ISD::UMULO) - VTs = DAG.getVTList(LHS.getValueType(), LHS.getValueType(), MVT::i32); - else - VTs = DAG.getVTList(LHS.getValueType(), MVT::i32); - - SDValue MxOp = DAG.getNode(MxOpcode, DL, VTs, LHS, RHS); - - if (CondOpcode == ISD::UMULO) - Cond = MxOp.getValue(2); - else - Cond = MxOp.getValue(1); - - CC = DAG.getConstant(MxCond, DL, MVT::i8); + } else if (isOverflowArithmetic(CondOpcode)) { + // Result is unused here. + SDValue Result; + unsigned CCode; + lowerOverflowArithmetic(Cond, DAG, Result, Cond, CCode); + CC = DAG.getConstant(CCode, DL, MVT::i8); addTest = false; } @@ -2377,6 +2405,17 @@ SDValue M68kTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { } } + // Simple optimization when Cond is a constant to avoid generating + // M68kISD::CMOV if possible. + // TODO: Generalize this to use SelectionDAG::computeKnownBits. + if (auto *Const = dyn_cast<ConstantSDNode>(Cond.getNode())) { + const APInt &C = Const->getAPIntValue(); + if (C.countr_zero() >= 5) + return Op2; + else if (C.countr_one() >= 5) + return Op1; + } + // M68kISD::CMOV means set the result (which is operand 1) to the RHS if // condition is true. SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); @@ -2466,61 +2505,15 @@ SDValue M68kTargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { } } CondOpcode = Cond.getOpcode(); - if (CondOpcode == ISD::UADDO || CondOpcode == ISD::SADDO || - CondOpcode == ISD::USUBO || CondOpcode == ISD::SSUBO) { - SDValue LHS = Cond.getOperand(0); - SDValue RHS = Cond.getOperand(1); - unsigned MxOpcode; - unsigned MxCond; - SDVTList VTs; - // Keep this in sync with LowerXALUO, otherwise we might create redundant - // instructions that can't be removed afterwards (i.e. M68kISD::ADD and - // M68kISD::INC). - switch (CondOpcode) { - case ISD::UADDO: - MxOpcode = M68kISD::ADD; - MxCond = M68k::COND_CS; - break; - case ISD::SADDO: - MxOpcode = M68kISD::ADD; - MxCond = M68k::COND_VS; - break; - case ISD::USUBO: - MxOpcode = M68kISD::SUB; - MxCond = M68k::COND_CS; - break; - case ISD::SSUBO: - MxOpcode = M68kISD::SUB; - MxCond = M68k::COND_VS; - break; - case ISD::UMULO: - MxOpcode = M68kISD::UMUL; - MxCond = M68k::COND_VS; - break; - case ISD::SMULO: - MxOpcode = M68kISD::SMUL; - MxCond = M68k::COND_VS; - break; - default: - llvm_unreachable("unexpected overflowing operator"); - } + if (isOverflowArithmetic(CondOpcode)) { + SDValue Result; + unsigned CCode; + lowerOverflowArithmetic(Cond, DAG, Result, Cond, CCode); if (Inverted) - MxCond = M68k::GetOppositeBranchCondition((M68k::CondCode)MxCond); + CCode = M68k::GetOppositeBranchCondition((M68k::CondCode)CCode); + CC = DAG.getConstant(CCode, DL, MVT::i8); - if (CondOpcode == ISD::UMULO) - VTs = DAG.getVTList(LHS.getValueType(), LHS.getValueType(), MVT::i8); - else - VTs = DAG.getVTList(LHS.getValueType(), MVT::i8); - - SDValue MxOp = DAG.getNode(MxOpcode, DL, VTs, LHS, RHS); - - if (CondOpcode == ISD::UMULO) - Cond = MxOp.getValue(2); - else - Cond = MxOp.getValue(1); - - CC = DAG.getConstant(MxCond, DL, MVT::i8); AddTest = false; } else { unsigned CondOpc; @@ -3394,7 +3387,7 @@ SDValue M68kTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, SDNode *Node = Op.getNode(); SDValue Chain = Op.getOperand(0); SDValue Size = Op.getOperand(1); - unsigned Align = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue(); + unsigned Align = Op.getConstantOperandVal(2); EVT VT = Node->getValueType(0); // Chain the dynamic stack allocation so that it doesn't modify the stack |
