Index: include/llvm/CodeGen/TargetLowering.h =================================================================== --- include/llvm/CodeGen/TargetLowering.h +++ include/llvm/CodeGen/TargetLowering.h @@ -2129,6 +2129,18 @@ return false; } + /// Return true if the target is to keep the SIGN_EXTEND from being combined + /// in certain conditions. + virtual bool keepSextNode(SDNode* N, SelectionDAG &DAG, const SDLoc &DL, + const SDValue &Op, unsigned DestBits) const { + return false; + } + /// Return true if the target is to keep the SIGN_EXTEND_INREG from being + /// combined in certain conditions. + virtual bool keepSextInRegNode(EVT VT) const { + return false; + } + /// Return true if the target supplies and combines to a paired load /// two loaded values of type LoadedType next to each other in memory. /// RequiredAlignment gives the minimal alignment constraints that must be met Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -8022,6 +8022,8 @@ unsigned NumSignBits = DAG.ComputeNumSignBits(Op); if (OpBits == DestBits) { + if (TLI.keepSextNode(N, DAG, DL, Op, DestBits)) + return SDValue(N, 0); // Op is i32, Mid is i8, and Dest is i32. If Op has more than 24 sign // bits, it is already ready. if (NumSignBits > DestBits-MidBits) @@ -8850,8 +8852,12 @@ return DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N), VT, N0, N1); // If the input is already sign extended, just drop the extension. - if (DAG.ComputeNumSignBits(N0) >= VTBits-EVTBits+1) - return N0; + if (DAG.ComputeNumSignBits(N0) >= VTBits-EVTBits+1) { + if (TLI.keepSextInRegNode(VT)) + return SDValue(N, 0); + else + return N0; + } // fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, minVT) pt2 if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG && Index: lib/Target/Mips/Mips64InstrInfo.td =================================================================== --- lib/Target/Mips/Mips64InstrInfo.td +++ lib/Target/Mips/Mips64InstrInfo.td @@ -804,6 +804,45 @@ def : MipsPat<(atomic_store_32 addr:$a, GPR64:$v), (SW64 GPR64:$v, addr:$a)>; def : MipsPat<(atomic_store_64 addr:$a, GPR64:$v), (SD GPR64:$v, addr:$a)>; +// Patterns used for matching away redundant sign extensions. +// MIPS32 arithmetic instructions sign extend their result implicitly. +def : MipsPat<(i64 (sext (i32 (add GPR32:$src, immSExt16:$imm16)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (ADDiu GPR32:$src, immSExt16:$imm16), sub_32)>; +def : MipsPat<(i64 (sext (i32 (add GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (ADDu GPR32:$src, GPR32:$src2), sub_32)>; +def : MipsPat<(i64 (sext (i32 (sub GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SUBu GPR32:$src, GPR32:$src2), sub_32)>; +def : MipsPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (MUL GPR32:$src, GPR32:$src2), sub_32)>; +def : MipsPat<(i64 (sext (i32 (MipsMFHI ACC64:$src)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (PseudoMFHI ACC64:$src), sub_32)>; +def : MipsPat<(i64 (sext (i32 (MipsMFLO ACC64:$src)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (PseudoMFLO ACC64:$src), sub_32)>; +def : MipsPat<(i64 (sext (i32 (shl GPR32:$src, immZExt5:$imm5)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SLL GPR32:$src, immZExt5:$imm5), sub_32)>; +def : MipsPat<(i64 (sext (i32 (shl GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SLLV GPR32:$src, GPR32:$src2), sub_32)>; +def : MipsPat<(i64 (sext (i32 (srl GPR32:$src, immZExt5:$imm5)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SRL GPR32:$src, immZExt5:$imm5), sub_32)>; +def : MipsPat<(i64 (sext (i32 (srl GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SRLV GPR32:$src, GPR32:$src2), sub_32)>; +def : MipsPat<(i64 (sext (i32 (sra GPR32:$src, immZExt5:$imm5)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SRA GPR32:$src, immZExt5:$imm5), sub_32)>; +def : MipsPat<(i64 (sext (i32 (sra GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SRAV GPR32:$src, GPR32:$src2), sub_32)>; + //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// Index: lib/Target/Mips/Mips64r6InstrInfo.td =================================================================== --- lib/Target/Mips/Mips64r6InstrInfo.td +++ lib/Target/Mips/Mips64r6InstrInfo.td @@ -299,6 +299,21 @@ (SELNEZ64 i64:$f, (SLL64_32 i32:$cond))>, ISA_MIPS64R6; +// Patterns used for matching away redundant sign extensions. +// MIPS32 arithmetic instructions sign extend their result implicitly. +def : MipsPat<(i64 (sext (i32 (sdiv GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (DIV GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; +def : MipsPat<(i64 (sext (i32 (udiv GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (DIVU GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; +def : MipsPat<(i64 (sext (i32 (srem GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (MOD GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; +def : MipsPat<(i64 (sext (i32 (urem GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (MODU GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; + // Pseudo instructions let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, Index: lib/Target/Mips/MipsISelLowering.h =================================================================== --- lib/Target/Mips/MipsISelLowering.h +++ lib/Target/Mips/MipsISelLowering.h @@ -277,6 +277,14 @@ return MVT::i32; } + EVT getTypeForExtReturn(LLVMContext &Context, EVT VT, + ISD::NodeType) const override; + + bool keepSextNode(SDNode* N, SelectionDAG &DAG, const SDLoc &DL, + const SDValue &Op, unsigned DestBits) const override; + + bool keepSextInRegNode(EVT VT) const override; + bool isCheapToSpeculateCttz() const override; bool isCheapToSpeculateCtlz() const override; Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -3713,6 +3713,28 @@ true); } +EVT MipsTargetLowering::getTypeForExtReturn(LLVMContext &Context, EVT VT, + ISD::NodeType) const { + bool Cond = !Subtarget.isABI_O32() && VT.getSizeInBits() == 32; + EVT MinVT = getRegisterType(Context, Cond ? MVT::i64 : MVT::i32); + return VT.bitsLT(MinVT) ? MinVT : VT; +} + +bool MipsTargetLowering::keepSextNode(SDNode* N, SelectionDAG &DAG, + const SDLoc &DL, const SDValue &Op, + unsigned DestBits) const { + if (DestBits != 64 || ABI.IsO32()) + return false; + SDValue InRegNode = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, Op, + DAG.getValueType(MVT::i32)); + DAG.ReplaceAllUsesWith(N, &InRegNode); + return true; +} + +bool MipsTargetLowering::keepSextInRegNode(EVT VT) const { + return VT == MVT::i64; +} + std::pair MipsTargetLowering:: parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { const TargetRegisterInfo *TRI = Index: test/CodeGen/Mips/delay-slot-kill.ll =================================================================== --- test/CodeGen/Mips/delay-slot-kill.ll +++ test/CodeGen/Mips/delay-slot-kill.ll @@ -1,6 +1,4 @@ ; RUN: llc < %s -march=mips64 -mcpu=mips3 | FileCheck %s -; We have to XFAIL this temporarily because of the reversion of r229675. -; XFAIL: * ; Currently, the following IR assembly generates a KILL instruction between ; the bitwise-and instruction and the return instruction. We verify that the @@ -8,8 +6,9 @@ ; return instruction properly. define signext i32 @f1(i32 signext %a, i32 signext %b) { entry: - ; CHECK: jr $ra - ; CHECK-NEXT: and $2, $4, $5 + ; CHECK: and $1, $4, $5 + ; CHECK-NEXT: jr $ra + ; CHECK-NEXT: sll $2, $1, 0 %r = and i32 %a, %b ret i32 %r Index: test/CodeGen/Mips/llvm-ir/not.ll =================================================================== --- test/CodeGen/Mips/llvm-ir/not.ll +++ test/CodeGen/Mips/llvm-ir/not.ll @@ -75,7 +75,8 @@ ; GP32: not $2, $4 - ; GP64: not $2, $4 + ; GP64: not $1, $4 + ; GP64: sll $2, $1, 0 ; MM: not16 $2, $4 @@ -169,7 +170,8 @@ ; GP64: or $[[T0:[0-9]+]], $5, $4 ; GP64: sll $[[T1:[0-9]+]], $[[T0]], 0 - ; GP64: not $2, $[[T1]] + ; GP64: not $[[T2:[0-9]+]], $[[T1]] + ; GP64: sll $2, $[[T2]], 0 ; MM32: nor $2, $5, $4 Index: test/CodeGen/Mips/llvm-ir/or.ll =================================================================== --- test/CodeGen/Mips/llvm-ir/or.ll +++ test/CodeGen/Mips/llvm-ir/or.ll @@ -284,8 +284,9 @@ ; ; GP64-LABEL: or_i32_4: ; GP64: # %bb.0: # %entry +; GP64-NEXT: ori $1, $4, 4 ; GP64-NEXT: jr $ra -; GP64-NEXT: ori $2, $4, 4 +; GP64-NEXT: sll $2, $1, 0 ; ; MM32-LABEL: or_i32_4: ; MM32: # %bb.0: # %entry @@ -450,8 +451,9 @@ ; ; GP64-LABEL: or_i32_31: ; GP64: # %bb.0: # %entry +; GP64-NEXT: ori $1, $4, 31 ; GP64-NEXT: jr $ra -; GP64-NEXT: ori $2, $4, 31 +; GP64-NEXT: sll $2, $1, 0 ; ; MM32-LABEL: or_i32_31: ; MM32: # %bb.0: # %entry @@ -616,8 +618,9 @@ ; ; GP64-LABEL: or_i32_255: ; GP64: # %bb.0: # %entry +; GP64-NEXT: ori $1, $4, 255 ; GP64-NEXT: jr $ra -; GP64-NEXT: ori $2, $4, 255 +; GP64-NEXT: sll $2, $1, 0 ; ; MM32-LABEL: or_i32_255: ; MM32: # %bb.0: # %entry @@ -786,8 +789,9 @@ ; ; GP64-LABEL: or_i32_32768: ; GP64: # %bb.0: # %entry +; GP64-NEXT: ori $1, $4, 32768 ; GP64-NEXT: jr $ra -; GP64-NEXT: ori $2, $4, 32768 +; GP64-NEXT: sll $2, $1, 0 ; ; MM32-LABEL: or_i32_32768: ; MM32: # %bb.0: # %entry @@ -952,8 +956,9 @@ ; ; GP64-LABEL: or_i32_65: ; GP64: # %bb.0: # %entry +; GP64-NEXT: ori $1, $4, 65 ; GP64-NEXT: jr $ra -; GP64-NEXT: ori $2, $4, 65 +; GP64-NEXT: sll $2, $1, 0 ; ; MM32-LABEL: or_i32_65: ; MM32: # %bb.0: # %entry @@ -1118,8 +1123,9 @@ ; ; GP64-LABEL: or_i32_256: ; GP64: # %bb.0: # %entry +; GP64-NEXT: ori $1, $4, 256 ; GP64-NEXT: jr $ra -; GP64-NEXT: ori $2, $4, 256 +; GP64-NEXT: sll $2, $1, 0 ; ; MM32-LABEL: or_i32_256: ; MM32: # %bb.0: # %entry Index: test/CodeGen/Mips/llvm-ir/select-int.ll =================================================================== --- test/CodeGen/Mips/llvm-ir/select-int.ll +++ test/CodeGen/Mips/llvm-ir/select-int.ll @@ -113,16 +113,17 @@ ; M2-M3: move $5, $6 ; M2-M3: [[BB0]]: ; M2-M3: jr $ra - ; M2-M3: move $2, $5 + ; M3: sll $2, $5, 0 ; CMOV: andi $[[T0:[0-9]+]], $4, 1 ; CMOV: movn $6, $5, $[[T0]] - ; CMOV: move $2, $6 + ; CMOV-64:sll $2, $6, 0 ; SEL: andi $[[T0:[0-9]+]], $4, 1 ; SEL: seleqz $[[T1:[0-9]+]], $6, $[[T0]] ; SEL: selnez $[[T2:[0-9]+]], $5, $[[T0]] - ; SEL: or $2, $[[T2]], $[[T1]] + ; SEL: or $[[T3:[0-9]+]], $[[T2]], $[[T1]] + ; SEL-64: sll $2, $[[T3]], 0 ; MM32R3: andi16 $[[T0:[0-9]+]], $4, 1 ; MM32R3: movn $[[T1:[0-9]+]], $5, $[[T0]] #