diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 55fc636d3c781..72f21a0d08b3c 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -521,7 +521,8 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::TRAP, MVT::Other, Legal); setTargetDAGCombine({ISD::SDIVREM, ISD::UDIVREM, ISD::SELECT, ISD::AND, - ISD::OR, ISD::ADD, ISD::SUB, ISD::AssertZext, ISD::SHL}); + ISD::OR, ISD::ADD, ISD::SUB, ISD::AssertZext, ISD::SHL, + ISD::SIGN_EXTEND}); if (Subtarget.isGP64bit()) setMaxAtomicSizeInBitsSupported(64); @@ -1221,6 +1222,37 @@ static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG, DAG.getConstant(SMSize, DL, MVT::i32)); } +static SDValue performSignExtendCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget &Subtarget) { + if (DCI.Level != AfterLegalizeDAG || !Subtarget.isGP64bit()) { + return SDValue(); + } + + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // Pattern match XOR. + // $dst = sign_extend (xor (trunc $src, i32), imm) + // => $dst = xor (signext_inreg $src, i32), imm + if (N0.getOpcode() == ISD::XOR && + N0.getOperand(0).getOpcode() == ISD::TRUNCATE && + N0.getOperand(1).getOpcode() == ISD::Constant) { + SDValue TruncateSource = N0.getOperand(0).getOperand(0); + auto *ConstantOperand = dyn_cast(N0->getOperand(1)); + + SDValue FirstOperand = + DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N0), VT, TruncateSource, + DAG.getValueType(N0.getOperand(0).getValueType())); + + int64_t ConstImm = ConstantOperand->getSExtValue(); + return DAG.getNode(ISD::XOR, SDLoc(N0), VT, FirstOperand, + DAG.getConstant(ConstImm, SDLoc(N0), VT)); + } + + return SDValue(); +} + SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -1246,6 +1278,8 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) return performSHLCombine(N, DAG, DCI, Subtarget); case ISD::SUB: return performSUBCombine(N, DAG, DCI, Subtarget); + case ISD::SIGN_EXTEND: + return performSignExtendCombine(N, DAG, DCI, Subtarget); } return SDValue(); diff --git a/llvm/test/CodeGen/Mips/llvm-ir/not.ll b/llvm/test/CodeGen/Mips/llvm-ir/not.ll index 58ed0e66d5e21..4fa50742e9acd 100644 --- a/llvm/test/CodeGen/Mips/llvm-ir/not.ll +++ b/llvm/test/CodeGen/Mips/llvm-ir/not.ll @@ -1,228 +1,346 @@ -; RUN: llc < %s -mtriple=mips -mcpu=mips2 | FileCheck %s -check-prefixes=ALL,GP32 -; RUN: llc < %s -mtriple=mips -mcpu=mips32 | FileCheck %s -check-prefixes=ALL,GP32 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 | FileCheck %s \ -; RUN: -check-prefixes=ALL,GP32 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 | FileCheck %s \ -; RUN: -check-prefixes=ALL,GP32 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r5 | FileCheck %s \ -; RUN: -check-prefixes=ALL,GP32 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 | FileCheck %s \ -; RUN: -check-prefixes=ALL,GP32 -; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 | FileCheck %s \ -; RUN: -check-prefixes=ALL,GP64 -; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 | FileCheck %s \ -; RUN: -check-prefixes=ALL,GP64 -; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 | FileCheck %s \ -; RUN: -check-prefixes=ALL,GP64 -; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 | FileCheck %s \ -; RUN: -check-prefixes=ALL,GP64 -; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r3 | FileCheck %s \ -; RUN: -check-prefixes=ALL,GP64 -; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r5 | FileCheck %s \ -; RUN: -check-prefixes=ALL,GP64 -; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r6 | FileCheck %s \ -; RUN: -check-prefixes=ALL,GP64 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips | FileCheck %s \ -; RUN: -check-prefixes=ALL,MM,MM32 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips | FileCheck %s \ -; RUN: -check-prefixes=ALL,MM,MM32 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips2 | FileCheck %s -check-prefixes=GP32 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32 | FileCheck %s -check-prefixes=GP32 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r2 | FileCheck %s \ +; RUN: -check-prefixes=GP32 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r3 | FileCheck %s \ +; RUN: -check-prefixes=GP32 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r5 | FileCheck %s \ +; RUN: -check-prefixes=GP32 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r6 | FileCheck %s \ +; RUN: -check-prefixes=GP32 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips3 | FileCheck %s \ +; RUN: -check-prefixes=GP64 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips4 | FileCheck %s \ +; RUN: -check-prefixes=GP64 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips64 | FileCheck %s \ +; RUN: -check-prefixes=GP64 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips64r2 | FileCheck %s \ +; RUN: -check-prefixes=GP64 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips64r3 | FileCheck %s \ +; RUN: -check-prefixes=GP64 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips64r5 | FileCheck %s \ +; RUN: -check-prefixes=GP64 +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -mcpu=mips64r6 | FileCheck %s \ +; RUN: -check-prefixes=GP64 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r3 -mattr=+micromips | FileCheck %s \ +; RUN: -check-prefixes=MM,MM32r3 +; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r6 -mattr=+micromips | FileCheck %s \ +; RUN: -check-prefixes=MM,MM32r6 define signext i1 @not_i1(i1 signext %a) { +; GP32-LABEL: not_i1: +; GP32: # %bb.0: # %entry +; GP32-NEXT: jr $ra +; GP32-NEXT: not $2, $4 +; +; GP64-LABEL: not_i1: +; GP64: # %bb.0: # %entry +; GP64-NEXT: jr $ra +; GP64-NEXT: not $2, $4 +; +; MM-LABEL: not_i1: +; MM: # %bb.0: # %entry +; MM-NEXT: not16 $2, $4 +; MM-NEXT: jrc $ra entry: -; ALL-LABEL: not_i1: - - ; GP32: not $2, $4 - - ; GP64: not $2, $4 - - ; MM: not16 $2, $4 - %r = xor i1 %a, -1 ret i1 %r } define signext i8 @not_i8(i8 signext %a) { +; GP32-LABEL: not_i8: +; GP32: # %bb.0: # %entry +; GP32-NEXT: jr $ra +; GP32-NEXT: not $2, $4 +; +; GP64-LABEL: not_i8: +; GP64: # %bb.0: # %entry +; GP64-NEXT: jr $ra +; GP64-NEXT: not $2, $4 +; +; MM-LABEL: not_i8: +; MM: # %bb.0: # %entry +; MM-NEXT: not16 $2, $4 +; MM-NEXT: jrc $ra entry: -; ALL-LABEL: not_i8: - - ; GP32: not $2, $4 - - ; GP64: not $2, $4 - - ; MM: not16 $2, $4 - %r = xor i8 %a, -1 ret i8 %r } define signext i16 @not_i16(i16 signext %a) { +; GP32-LABEL: not_i16: +; GP32: # %bb.0: # %entry +; GP32-NEXT: jr $ra +; GP32-NEXT: not $2, $4 +; +; GP64-LABEL: not_i16: +; GP64: # %bb.0: # %entry +; GP64-NEXT: jr $ra +; GP64-NEXT: not $2, $4 +; +; MM-LABEL: not_i16: +; MM: # %bb.0: # %entry +; MM-NEXT: not16 $2, $4 +; MM-NEXT: jrc $ra entry: -; ALL-LABEL: not_i16: - - ; GP32: not $2, $4 - - ; GP64: not $2, $4 - - ; MM: not16 $2, $4 - %r = xor i16 %a, -1 ret i16 %r } define signext i32 @not_i32(i32 signext %a) { +; GP32-LABEL: not_i32: +; GP32: # %bb.0: # %entry +; GP32-NEXT: jr $ra +; GP32-NEXT: not $2, $4 +; +; GP64-LABEL: not_i32: +; GP64: # %bb.0: # %entry +; GP64-NEXT: daddiu $1, $zero, -1 +; GP64-NEXT: jr $ra +; GP64-NEXT: xor $2, $4, $1 +; +; MM-LABEL: not_i32: +; MM: # %bb.0: # %entry +; MM-NEXT: not16 $2, $4 +; MM-NEXT: jrc $ra entry: -; ALL-LABEL: not_i32: - - ; GP32: not $2, $4 - - ; GP64: not $1, $4 - ; GP64: sll $2, $1, 0 - - ; MM: not16 $2, $4 - %r = xor i32 %a, -1 ret i32 %r } define signext i64 @not_i64(i64 signext %a) { +; GP32-LABEL: not_i64: +; GP32: # %bb.0: # %entry +; GP32-NEXT: not $2, $4 +; GP32-NEXT: jr $ra +; GP32-NEXT: not $3, $5 +; +; GP64-LABEL: not_i64: +; GP64: # %bb.0: # %entry +; GP64-NEXT: daddiu $1, $zero, -1 +; GP64-NEXT: jr $ra +; GP64-NEXT: xor $2, $4, $1 +; +; MM-LABEL: not_i64: +; MM: # %bb.0: # %entry +; MM-NEXT: not16 $2, $4 +; MM-NEXT: not16 $3, $5 +; MM-NEXT: jrc $ra entry: -; ALL-LABEL: not_i64: - - ; GP32: not $2, $4 - ; GP32: not $3, $5 - - ; GP64: daddiu $[[T0:[0-9]+]], $zero, -1 - ; GP64: xor $2, $4, $[[T0]] - - ; MM32: not16 $2, $4 - ; MM32: not16 $3, $5 - %r = xor i64 %a, -1 ret i64 %r } define signext i128 @not_i128(i128 signext %a) { +; GP32-LABEL: not_i128: +; GP32: # %bb.0: # %entry +; GP32-NEXT: not $2, $4 +; GP32-NEXT: not $3, $5 +; GP32-NEXT: not $4, $6 +; GP32-NEXT: jr $ra +; GP32-NEXT: not $5, $7 +; +; GP64-LABEL: not_i128: +; GP64: # %bb.0: # %entry +; GP64-NEXT: daddiu $1, $zero, -1 +; GP64-NEXT: xor $2, $4, $1 +; GP64-NEXT: jr $ra +; GP64-NEXT: xor $3, $5, $1 +; +; MM-LABEL: not_i128: +; MM: # %bb.0: # %entry +; MM-NEXT: not16 $2, $4 +; MM-NEXT: not16 $3, $5 +; MM-NEXT: not16 $4, $6 +; MM-NEXT: not16 $5, $7 +; MM-NEXT: jrc $ra entry: -; ALL-LABEL: not_i128: - - ; GP32: not $2, $4 - ; GP32: not $3, $5 - ; GP32: not $4, $6 - ; GP32: not $5, $7 - - ; GP64: daddiu $[[T0:[0-9]+]], $zero, -1 - ; GP64: xor $2, $4, $[[T0]] - ; GP64: xor $3, $5, $[[T0]] - - ; MM32: not16 $2, $4 - ; MM32: not16 $3, $5 - ; MM32: not16 $4, $6 - ; MM32: not16 $5, $7 - %r = xor i128 %a, -1 ret i128 %r } define signext i1 @nor_i1(i1 signext %a, i1 signext %b) { +; GP32-LABEL: nor_i1: +; GP32: # %bb.0: # %entry +; GP32-NEXT: jr $ra +; GP32-NEXT: nor $2, $5, $4 +; +; GP64-LABEL: nor_i1: +; GP64: # %bb.0: # %entry +; GP64-NEXT: or $1, $5, $4 +; GP64-NEXT: sll $1, $1, 0 +; GP64-NEXT: jr $ra +; GP64-NEXT: not $2, $1 +; +; MM32r3-LABEL: nor_i1: +; MM32r3: # %bb.0: # %entry +; MM32r3-NEXT: jr $ra +; MM32r3-NEXT: nor $2, $5, $4 +; +; MM32r6-LABEL: nor_i1: +; MM32r6: # %bb.0: # %entry +; MM32r6-NEXT: nor $2, $5, $4 +; MM32r6-NEXT: jrc $ra entry: -; ALL-LABEL: nor_i1: - - ; GP32: nor $2, $5, $4 - ; GP64: or $1, $5, $4 - ; MM32: nor $2, $5, $4 - %or = or i1 %b, %a %r = xor i1 %or, -1 ret i1 %r } define signext i8 @nor_i8(i8 signext %a, i8 signext %b) { +; GP32-LABEL: nor_i8: +; GP32: # %bb.0: # %entry +; GP32-NEXT: jr $ra +; GP32-NEXT: nor $2, $5, $4 +; +; GP64-LABEL: nor_i8: +; GP64: # %bb.0: # %entry +; GP64-NEXT: or $1, $5, $4 +; GP64-NEXT: sll $1, $1, 0 +; GP64-NEXT: jr $ra +; GP64-NEXT: not $2, $1 +; +; MM32r3-LABEL: nor_i8: +; MM32r3: # %bb.0: # %entry +; MM32r3-NEXT: jr $ra +; MM32r3-NEXT: nor $2, $5, $4 +; +; MM32r6-LABEL: nor_i8: +; MM32r6: # %bb.0: # %entry +; MM32r6-NEXT: nor $2, $5, $4 +; MM32r6-NEXT: jrc $ra entry: -; ALL-LABEL: nor_i8: - - ; GP32: nor $2, $5, $4 - ; GP64: or $1, $5, $4 - ; MM32: nor $2, $5, $4 - %or = or i8 %b, %a %r = xor i8 %or, -1 ret i8 %r } define signext i16 @nor_i16(i16 signext %a, i16 signext %b) { +; GP32-LABEL: nor_i16: +; GP32: # %bb.0: # %entry +; GP32-NEXT: jr $ra +; GP32-NEXT: nor $2, $5, $4 +; +; GP64-LABEL: nor_i16: +; GP64: # %bb.0: # %entry +; GP64-NEXT: or $1, $5, $4 +; GP64-NEXT: sll $1, $1, 0 +; GP64-NEXT: jr $ra +; GP64-NEXT: not $2, $1 +; +; MM32r3-LABEL: nor_i16: +; MM32r3: # %bb.0: # %entry +; MM32r3-NEXT: jr $ra +; MM32r3-NEXT: nor $2, $5, $4 +; +; MM32r6-LABEL: nor_i16: +; MM32r6: # %bb.0: # %entry +; MM32r6-NEXT: nor $2, $5, $4 +; MM32r6-NEXT: jrc $ra entry: -; ALL-LABEL: nor_i16: - - ; GP32: nor $2, $5, $4 - ; GP64: or $1, $5, $4 - ; MM32: nor $2, $5, $4 - %or = or i16 %b, %a %r = xor i16 %or, -1 ret i16 %r } define signext i32 @nor_i32(i32 signext %a, i32 signext %b) { +; GP32-LABEL: nor_i32: +; GP32: # %bb.0: # %entry +; GP32-NEXT: jr $ra +; GP32-NEXT: nor $2, $5, $4 +; +; GP64-LABEL: nor_i32: +; GP64: # %bb.0: # %entry +; GP64-NEXT: jr $ra +; GP64-NEXT: nor $2, $5, $4 +; +; MM32r3-LABEL: nor_i32: +; MM32r3: # %bb.0: # %entry +; MM32r3-NEXT: jr $ra +; MM32r3-NEXT: nor $2, $5, $4 +; +; MM32r6-LABEL: nor_i32: +; MM32r6: # %bb.0: # %entry +; MM32r6-NEXT: nor $2, $5, $4 +; MM32r6-NEXT: jrc $ra entry: -; ALL-LABEL: nor_i32: - - ; GP32: nor $2, $5, $4 - - ; GP64: or $[[T0:[0-9]+]], $5, $4 - ; GP64: sll $[[T1:[0-9]+]], $[[T0]], 0 - ; GP64: not $[[T2:[0-9]+]], $[[T1]] - ; GP64: sll $2, $[[T2]], 0 - - ; MM32: nor $2, $5, $4 - %or = or i32 %b, %a %r = xor i32 %or, -1 ret i32 %r } - define signext i64 @nor_i64(i64 signext %a, i64 signext %b) { +; GP32-LABEL: nor_i64: +; GP32: # %bb.0: # %entry +; GP32-NEXT: nor $2, $6, $4 +; GP32-NEXT: jr $ra +; GP32-NEXT: nor $3, $7, $5 +; +; GP64-LABEL: nor_i64: +; GP64: # %bb.0: # %entry +; GP64-NEXT: jr $ra +; GP64-NEXT: nor $2, $5, $4 +; +; MM32r3-LABEL: nor_i64: +; MM32r3: # %bb.0: # %entry +; MM32r3-NEXT: nor $2, $6, $4 +; MM32r3-NEXT: jr $ra +; MM32r3-NEXT: nor $3, $7, $5 +; +; MM32r6-LABEL: nor_i64: +; MM32r6: # %bb.0: # %entry +; MM32r6-NEXT: nor $2, $6, $4 +; MM32r6-NEXT: nor $3, $7, $5 +; MM32r6-NEXT: jrc $ra entry: -; ALL-LABEL: nor_i64: - - ; GP32: nor $2, $6, $4 - ; GP32: nor $3, $7, $5 - - ; GP64: nor $2, $5, $4 - - ; MM32: nor $2, $6, $4 - ; MM32: nor $3, $7, $5 - %or = or i64 %b, %a %r = xor i64 %or, -1 ret i64 %r } define signext i128 @nor_i128(i128 signext %a, i128 signext %b) { +; GP32-LABEL: nor_i128: +; GP32: # %bb.0: # %entry +; GP32-NEXT: lw $1, 20($sp) +; GP32-NEXT: lw $2, 16($sp) +; GP32-NEXT: nor $2, $2, $4 +; GP32-NEXT: nor $3, $1, $5 +; GP32-NEXT: lw $1, 24($sp) +; GP32-NEXT: nor $4, $1, $6 +; GP32-NEXT: lw $1, 28($sp) +; GP32-NEXT: jr $ra +; GP32-NEXT: nor $5, $1, $7 +; +; GP64-LABEL: nor_i128: +; GP64: # %bb.0: # %entry +; GP64-NEXT: nor $2, $6, $4 +; GP64-NEXT: jr $ra +; GP64-NEXT: nor $3, $7, $5 +; +; MM32r3-LABEL: nor_i128: +; MM32r3: # %bb.0: # %entry +; MM32r3-NEXT: lw $1, 20($sp) +; MM32r3-NEXT: lw $2, 16($sp) +; MM32r3-NEXT: nor $2, $2, $4 +; MM32r3-NEXT: nor $3, $1, $5 +; MM32r3-NEXT: lw $1, 24($sp) +; MM32r3-NEXT: nor $4, $1, $6 +; MM32r3-NEXT: lw $1, 28($sp) +; MM32r3-NEXT: jr $ra +; MM32r3-NEXT: nor $5, $1, $7 +; +; MM32r6-LABEL: nor_i128: +; MM32r6: # %bb.0: # %entry +; MM32r6-NEXT: lw $1, 20($sp) +; MM32r6-NEXT: lw $2, 16($sp) +; MM32r6-NEXT: nor $2, $2, $4 +; MM32r6-NEXT: nor $3, $1, $5 +; MM32r6-NEXT: lw $1, 24($sp) +; MM32r6-NEXT: nor $4, $1, $6 +; MM32r6-NEXT: lw $1, 28($sp) +; MM32r6-NEXT: nor $5, $1, $7 +; MM32r6-NEXT: jrc $ra entry: -; ALL-LABEL: nor_i128: - - ; GP32: lw $[[T1:[0-9]+]], 20($sp) - ; GP32: lw $[[T2:[0-9]+]], 16($sp) - ; GP32: nor $2, $[[T2]], $4 - ; GP32: nor $3, $[[T1]], $5 - ; GP32: lw $[[T0:[0-9]+]], 24($sp) - ; GP32: nor $4, $[[T0]], $6 - ; GP32: lw $[[T3:[0-9]+]], 28($sp) - ; GP32: nor $5, $[[T3]], $7 - - ; GP64: nor $2, $6, $4 - ; GP64: nor $3, $7, $5 - - ; MM32: lw $[[T1:[0-9]+]], 20($sp) - ; MM32: lw $[[T2:[0-9]+]], 16($sp) - ; MM32: nor $2, $[[T2]], $4 - ; MM32: nor $3, $[[T1]], $5 - ; MM32: lw $[[T0:[0-9]+]], 24($sp) - ; MM32: nor $4, $[[T0]], $6 - ; MM32: lw $[[T3:[0-9]+]], 28($sp) - ; MM32: nor $5, $[[T3]], $7 - %or = or i128 %b, %a %r = xor i128 %or, -1 ret i128 %r diff --git a/llvm/test/CodeGen/Mips/llvm-ir/xor.ll b/llvm/test/CodeGen/Mips/llvm-ir/xor.ll index 972e3b6685a65..ec9a204b2b431 100644 --- a/llvm/test/CodeGen/Mips/llvm-ir/xor.ll +++ b/llvm/test/CodeGen/Mips/llvm-ir/xor.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips2 | FileCheck %s -check-prefix=MIPS ; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32 | FileCheck %s -check-prefix=MIPS ; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r2 | FileCheck %s \ @@ -508,21 +507,18 @@ 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: sll $2, $1, 0 +; MIPS64-NEXT: xori $2, $4, 4 ; ; MIPS64R2-LABEL: xor_i32_4: ; MIPS64R2: # %bb.0: # %entry -; MIPS64R2-NEXT: xori $1, $4, 4 ; MIPS64R2-NEXT: jr $ra -; MIPS64R2-NEXT: sll $2, $1, 0 +; MIPS64R2-NEXT: xori $2, $4, 4 ; ; MIPS64R6-LABEL: xor_i32_4: ; MIPS64R6: # %bb.0: # %entry -; MIPS64R6-NEXT: xori $1, $4, 4 ; MIPS64R6-NEXT: jr $ra -; MIPS64R6-NEXT: sll $2, $1, 0 +; MIPS64R6-NEXT: xori $2, $4, 4 ; ; MM32R3-LABEL: xor_i32_4: ; MM32R3: # %bb.0: # %entry diff --git a/llvm/test/CodeGen/Mips/xor-and.ll b/llvm/test/CodeGen/Mips/xor-and.ll index 3a173baf205d3..efe0af1f999f9 100644 --- a/llvm/test/CodeGen/Mips/xor-and.ll +++ b/llvm/test/CodeGen/Mips/xor-and.ll @@ -1,17 +1,45 @@ -; RUN: llc -O3 -mcpu=mips64r6 -mtriple=mips64el-unknown-linux-gnuabi64 < %s -o - | FileCheck %s +; RUN: llc -O3 -mcpu=mips64 -mtriple=mips64el-unknown-linux-gnuabi64 < %s -o - | FileCheck %s -; This test shows the unoptimized result with unnecessary SLLs. define noundef signext i32 @xor_and(i32 noundef signext %a, i32 noundef signext %b) local_unnamed_addr { ; CHECK-LABEL: xor_and: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: and $1, $5, $4 -; CHECK-NEXT: sll $1, $1, 0 -; CHECK-NEXT: not $1, $1 +; CHECK-NEXT: daddiu $2, $zero, -1 ; CHECK-NEXT: jr $ra -; CHECK-NEXT: sll $2, $1, 0 +; CHECK-NEXT: xor $2, $1, $2 entry: %0 = and i32 %b, %a %or1 = xor i32 %0, -1 ret i32 %or1 } + +define noundef signext i32 @input_i16(i16 noundef signext %a, i16 noundef signext %b) local_unnamed_addr { +; CHECK-LABEL: input_i16: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: and $1, $5, $4 +; CHECK-NEXT: daddiu $2, $zero, -1 +; CHECK-NEXT: jr $ra +; CHECK-NEXT: xor $2, $1, $2 + +entry: + %0 = and i16 %b, %a + %1 = xor i16 %0, -1 + %or4 = sext i16 %1 to i32 + ret i32 %or4 +} + +define i64 @return_i64(i32 noundef signext %a, i32 noundef signext %b) local_unnamed_addr { +; CHECK-LABEL: return_i64: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: and $1, $5, $4 +; CHECK-NEXT: daddiu $2, $zero, -1 +; CHECK-NEXT: jr $ra +; CHECK-NEXT: xor $2, $1, $2 + +entry: + %0 = and i32 %b, %a + %or1 = xor i32 %0, -1 + %conv = sext i32 %or1 to i64 + ret i64 %conv +}