diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -1536,6 +1536,7 @@ bool RISCVDAGToDAGISel::hasAllNBitUsers(SDNode *Node, unsigned Bits) const { assert((Node->getOpcode() == ISD::ADD || Node->getOpcode() == ISD::SUB || Node->getOpcode() == ISD::MUL || Node->getOpcode() == ISD::SHL || + Node->getOpcode() == ISD::SIGN_EXTEND_INREG || isa(Node)) && "Unexpected opcode"); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1262,10 +1262,18 @@ return hasAllWUsers(Node); }]>; +def sexti32_allwusers : PatFrag<(ops node:$src), + (sext_inreg node:$src, i32), [{ + return hasAllWUsers(Node); +}]>; + let Predicates = [IsRV64] in { /// sext and zext +// Sign extend is not needed if all users are W instructions. +def : Pat<(sexti32_allwusers GPR:$rs1), (XLenVT GPR:$rs1)>; + def : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>; /// ALU operations diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -376,7 +376,6 @@ ; to remove the sext_inreg because it has multiple uses. The ashr will use the ; sext_inreg to become sraiw. This leaves the sext_inreg only used by the shl. ; If the shl is selected as sllw, we don't need the sext_inreg. -; FIXME: We should not emit a sext.w. define i64 @sh2add_extra_sext(i32 %x, i32 %y, i32 %z) { ; RV64I-LABEL: sh2add_extra_sext: ; RV64I: # %bb.0: @@ -390,8 +389,7 @@ ; RV64B-LABEL: sh2add_extra_sext: ; RV64B: # %bb.0: ; RV64B-NEXT: sh2add a0, a0, a1 -; RV64B-NEXT: sext.w a1, a0 -; RV64B-NEXT: sllw a1, a2, a1 +; RV64B-NEXT: sllw a1, a2, a0 ; RV64B-NEXT: sraiw a0, a0, 2 ; RV64B-NEXT: mul a0, a1, a0 ; RV64B-NEXT: ret @@ -399,8 +397,7 @@ ; RV64ZBA-LABEL: sh2add_extra_sext: ; RV64ZBA: # %bb.0: ; RV64ZBA-NEXT: sh2add a0, a0, a1 -; RV64ZBA-NEXT: sext.w a1, a0 -; RV64ZBA-NEXT: sllw a1, a2, a1 +; RV64ZBA-NEXT: sllw a1, a2, a0 ; RV64ZBA-NEXT: sraiw a0, a0, 2 ; RV64ZBA-NEXT: mul a0, a1, a0 ; RV64ZBA-NEXT: ret