Index: llvm/trunk/lib/Target/Mips/Mips64InstrInfo.td =================================================================== --- llvm/trunk/lib/Target/Mips/Mips64InstrInfo.td +++ llvm/trunk/lib/Target/Mips/Mips64InstrInfo.td @@ -825,6 +825,45 @@ def : MipsPat<(atomic_store_64 addr:$a, GPR64:$v), (SD GPR64:$v, addr:$a)>, ISA_MIPS3, GPR_64; +// 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: llvm/trunk/lib/Target/Mips/Mips64r6InstrInfo.td =================================================================== --- llvm/trunk/lib/Target/Mips/Mips64r6InstrInfo.td +++ llvm/trunk/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: llvm/trunk/lib/Target/Mips/MipsISelLowering.h =================================================================== --- llvm/trunk/lib/Target/Mips/MipsISelLowering.h +++ llvm/trunk/lib/Target/Mips/MipsISelLowering.h @@ -280,6 +280,9 @@ return MVT::i32; } + EVT getTypeForExtReturn(LLVMContext &Context, EVT VT, + ISD::NodeType) const override; + bool isCheapToSpeculateCttz() const override; bool isCheapToSpeculateCtlz() const override; Index: llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp +++ llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp @@ -3714,6 +3714,13 @@ 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; +} + std::pair MipsTargetLowering:: parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { const TargetRegisterInfo *TRI = Index: llvm/trunk/test/CodeGen/Mips/delay-slot-kill.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/delay-slot-kill.ll +++ llvm/trunk/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 Index: llvm/trunk/test/CodeGen/Mips/llvm-ir/and.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/llvm-ir/and.ll +++ llvm/trunk/test/CodeGen/Mips/llvm-ir/and.ll @@ -195,21 +195,18 @@ ; ; MIPS64-LABEL: and_i32: ; MIPS64: # %bb.0: # %entry -; MIPS64-NEXT: and $1, $4, $5 ; MIPS64-NEXT: jr $ra -; MIPS64-NEXT: sll $2, $1, 0 +; MIPS64-NEXT: and $2, $4, $5 ; ; MIPS64R2-LABEL: and_i32: ; MIPS64R2: # %bb.0: # %entry -; MIPS64R2-NEXT: and $1, $4, $5 ; MIPS64R2-NEXT: jr $ra -; MIPS64R2-NEXT: sll $2, $1, 0 +; MIPS64R2-NEXT: and $2, $4, $5 ; ; MIPS64R6-LABEL: and_i32: ; MIPS64R6: # %bb.0: # %entry -; MIPS64R6-NEXT: and $1, $4, $5 ; MIPS64R6-NEXT: jr $ra -; MIPS64R6-NEXT: sll $2, $1, 0 +; MIPS64R6-NEXT: and $2, $4, $5 ; ; MM32R3-LABEL: and_i32: ; MM32R3: # %bb.0: # %entry Index: llvm/trunk/test/CodeGen/Mips/llvm-ir/not.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/llvm-ir/not.ll +++ llvm/trunk/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: llvm/trunk/test/CodeGen/Mips/llvm-ir/or.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/llvm-ir/or.ll +++ llvm/trunk/test/CodeGen/Mips/llvm-ir/or.ll @@ -106,9 +106,8 @@ ; ; GP64-LABEL: or_i32: ; GP64: # %bb.0: # %entry -; GP64-NEXT: or $1, $4, $5 ; GP64-NEXT: jr $ra -; GP64-NEXT: sll $2, $1, 0 +; GP64-NEXT: or $2, $4, $5 ; ; MM32-LABEL: or_i32: ; MM32: # %bb.0: # %entry @@ -284,8 +283,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 +450,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 +617,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 +788,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 +955,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 +1122,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: llvm/trunk/test/CodeGen/Mips/llvm-ir/select-int.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/llvm-ir/select-int.ll +++ llvm/trunk/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]] #