[mips] Sign extend i32 return values on MIPS64

Override getTypeForExtReturn so that functions returning
an i32 typed value have it sign extended on MIPS64.

Also provide patterns to get rid of unneeded sign extensions
for arithmetic instructions which implicitly sign extend
their results.

Differential Revision: https://reviews.llvm.org/D48374


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@338019 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Stefan Maksimovic
2018-07-26 10:59:35 +00:00
parent 078cc9c528
commit 4f48c840d0
11 changed files with 101 additions and 38 deletions
+39
View File
@@ -825,6 +825,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)>,
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
//===----------------------------------------------------------------------===//
+15
View File
@@ -299,6 +299,21 @@ def : MipsPat<(select (i32 (seteq i32:$cond, immz)), immz, i64:$f),
(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,
+7
View File
@@ -3714,6 +3714,13 @@ static std::pair<bool, bool> parsePhysicalReg(StringRef C, StringRef &Prefix,
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<unsigned, const TargetRegisterClass *> MipsTargetLowering::
parseRegForInlineAsmConstraint(StringRef C, MVT VT) const {
const TargetRegisterInfo *TRI =
+3
View File
@@ -280,6 +280,9 @@ class TargetRegisterClass;
return MVT::i32;
}
EVT getTypeForExtReturn(LLVMContext &Context, EVT VT,
ISD::NodeType) const override;
bool isCheapToSpeculateCttz() const override;
bool isCheapToSpeculateCtlz() const override;
-2
View File
@@ -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
+3 -6
View File
@@ -195,21 +195,18 @@ define signext i32 @and_i32(i32 signext %a, i32 signext %b) {
;
; 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
+4 -2
View File
@@ -75,7 +75,8 @@ entry:
; 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 @@ entry:
; 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
+13 -8
View File
@@ -106,9 +106,8 @@ define signext i32 @or_i32(i32 signext %a, i32 signext %b) {
;
; 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 @@ define signext i32 @or_i32_4(i32 signext %b) {
;
; 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 @@ define signext i32 @or_i32_31(i32 signext %b) {
;
; 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 @@ define signext i32 @or_i32_255(i32 signext %b) {
;
; 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 @@ define signext i32 @or_i32_32768(i32 signext %b) {
;
; 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 @@ define signext i32 @or_i32_65(i32 signext %b) {
;
; 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 @@ define signext i32 @or_i32_256(i32 signext %b) {
;
; 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
+4 -3
View File
@@ -113,16 +113,17 @@ entry:
; 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]] # <MCInst #{{[0-9]+}} MOVN_I_MM
+9 -9
View File
@@ -193,21 +193,18 @@ define signext i32 @xor_i32(i32 signext %a, i32 signext %b) {
;
; MIPS64-LABEL: xor_i32:
; MIPS64: # %bb.0: # %entry
; MIPS64-NEXT: xor $1, $4, $5
; MIPS64-NEXT: jr $ra
; MIPS64-NEXT: sll $2, $1, 0
; MIPS64-NEXT: xor $2, $4, $5
;
; MIPS64R2-LABEL: xor_i32:
; MIPS64R2: # %bb.0: # %entry
; MIPS64R2-NEXT: xor $1, $4, $5
; MIPS64R2-NEXT: jr $ra
; MIPS64R2-NEXT: sll $2, $1, 0
; MIPS64R2-NEXT: xor $2, $4, $5
;
; MIPS64R6-LABEL: xor_i32:
; MIPS64R6: # %bb.0: # %entry
; MIPS64R6-NEXT: xor $1, $4, $5
; MIPS64R6-NEXT: jr $ra
; MIPS64R6-NEXT: sll $2, $1, 0
; MIPS64R6-NEXT: xor $2, $4, $5
;
; MM32R3-LABEL: xor_i32:
; MM32R3: # %bb.0: # %entry
@@ -511,18 +508,21 @@ define signext i32 @xor_i32_4(i32 signext %b) {
;
; MIPS64-LABEL: xor_i32_4:
; MIPS64: # %bb.0: # %entry
; MIPS64-NEXT: xori $1, $4, 4
; MIPS64-NEXT: jr $ra
; MIPS64-NEXT: xori $2, $4, 4
; MIPS64-NEXT: sll $2, $1, 0
;
; MIPS64R2-LABEL: xor_i32_4:
; MIPS64R2: # %bb.0: # %entry
; MIPS64R2-NEXT: xori $1, $4, 4
; MIPS64R2-NEXT: jr $ra
; MIPS64R2-NEXT: xori $2, $4, 4
; MIPS64R2-NEXT: sll $2, $1, 0
;
; MIPS64R6-LABEL: xor_i32_4:
; MIPS64R6: # %bb.0: # %entry
; MIPS64R6-NEXT: xori $1, $4, 4
; MIPS64R6-NEXT: jr $ra
; MIPS64R6-NEXT: xori $2, $4, 4
; MIPS64R6-NEXT: sll $2, $1, 0
;
; MM32R3-LABEL: xor_i32_4:
; MM32R3: # %bb.0: # %entry
+4 -8
View File
@@ -118,9 +118,8 @@ define i32 @foo(i32 signext %a) {
; SHRINK-WRAP-64-STATIC-NEXT: .cfi_def_cfa_offset 16
; SHRINK-WRAP-64-STATIC-NEXT: sd $ra, 8($sp) # 8-byte Folded Spill
; SHRINK-WRAP-64-STATIC-NEXT: .cfi_offset 31, -8
; SHRINK-WRAP-64-STATIC-NEXT: addiu $1, $4, 1
; SHRINK-WRAP-64-STATIC-NEXT: jal f
; SHRINK-WRAP-64-STATIC-NEXT: sll $4, $1, 0
; SHRINK-WRAP-64-STATIC-NEXT: addiu $4, $4, 1
; SHRINK-WRAP-64-STATIC-NEXT: ld $ra, 8($sp) # 8-byte Folded Reload
; SHRINK-WRAP-64-STATIC-NEXT: daddiu $sp, $sp, 16
; SHRINK-WRAP-64-STATIC-NEXT: .LBB0_2: # %return
@@ -136,9 +135,8 @@ define i32 @foo(i32 signext %a) {
; NO-SHRINK-WRAP-64-STATIC-NEXT: beqz $4, .LBB0_2
; NO-SHRINK-WRAP-64-STATIC-NEXT: nop
; NO-SHRINK-WRAP-64-STATIC-NEXT: # %bb.1: # %if.end
; NO-SHRINK-WRAP-64-STATIC-NEXT: addiu $1, $4, 1
; NO-SHRINK-WRAP-64-STATIC-NEXT: jal f
; NO-SHRINK-WRAP-64-STATIC-NEXT: sll $4, $1, 0
; NO-SHRINK-WRAP-64-STATIC-NEXT: addiu $4, $4, 1
; NO-SHRINK-WRAP-64-STATIC-NEXT: .LBB0_2: # %return
; NO-SHRINK-WRAP-64-STATIC-NEXT: addiu $2, $zero, 0
; NO-SHRINK-WRAP-64-STATIC-NEXT: ld $ra, 8($sp) # 8-byte Folded Reload
@@ -158,10 +156,9 @@ define i32 @foo(i32 signext %a) {
; SHRINK-WRAP-64-PIC-NEXT: .cfi_offset 31, -8
; SHRINK-WRAP-64-PIC-NEXT: .cfi_offset 28, -16
; SHRINK-WRAP-64-PIC-NEXT: daddiu $gp, $2, %lo(%neg(%gp_rel(foo)))
; SHRINK-WRAP-64-PIC-NEXT: addiu $1, $4, 1
; SHRINK-WRAP-64-PIC-NEXT: ld $25, %call16(f)($gp)
; SHRINK-WRAP-64-PIC-NEXT: jalr $25
; SHRINK-WRAP-64-PIC-NEXT: sll $4, $1, 0
; SHRINK-WRAP-64-PIC-NEXT: addiu $4, $4, 1
; SHRINK-WRAP-64-PIC-NEXT: ld $gp, 0($sp) # 8-byte Folded Reload
; SHRINK-WRAP-64-PIC-NEXT: ld $ra, 8($sp) # 8-byte Folded Reload
; SHRINK-WRAP-64-PIC-NEXT: daddiu $sp, $sp, 16
@@ -182,10 +179,9 @@ define i32 @foo(i32 signext %a) {
; NO-SHRINK-WRAP-64-PIC-NEXT: daddu $2, $1, $25
; NO-SHRINK-WRAP-64-PIC-NEXT: # %bb.1: # %if.end
; NO-SHRINK-WRAP-64-PIC-NEXT: daddiu $gp, $2, %lo(%neg(%gp_rel(foo)))
; NO-SHRINK-WRAP-64-PIC-NEXT: addiu $1, $4, 1
; NO-SHRINK-WRAP-64-PIC-NEXT: ld $25, %call16(f)($gp)
; NO-SHRINK-WRAP-64-PIC-NEXT: jalr $25
; NO-SHRINK-WRAP-64-PIC-NEXT: sll $4, $1, 0
; NO-SHRINK-WRAP-64-PIC-NEXT: addiu $4, $4, 1
; NO-SHRINK-WRAP-64-PIC-NEXT: .LBB0_2: # %return
; NO-SHRINK-WRAP-64-PIC-NEXT: addiu $2, $zero, 0
; NO-SHRINK-WRAP-64-PIC-NEXT: ld $gp, 0($sp) # 8-byte Folded Reload