diff --git a/llvm/lib/Target/RISCV/RISCVSExtWRemoval.cpp b/llvm/lib/Target/RISCV/RISCVSExtWRemoval.cpp index 113a493a998f..73b9d67f4cc2 100644 --- a/llvm/lib/Target/RISCV/RISCVSExtWRemoval.cpp +++ b/llvm/lib/Target/RISCV/RISCVSExtWRemoval.cpp @@ -6,7 +6,9 @@ // //===---------------------------------------------------------------------===// // -// This pass removes unneeded sext.w instructions at the MI level. +// This pass removes unneeded sext.w instructions at the MI level. Either +// because the sign extended bits aren't consumed or because the input was +// already sign extended by an earlier instruction. // //===---------------------------------------------------------------------===// @@ -479,9 +481,10 @@ bool RISCVSExtWRemoval::runOnMachineFunction(MachineFunction &MF) { SmallPtrSet FixableDefs; - // If all definitions reaching MI sign-extend their output, - // then sext.w is redundant - if (!isSignExtendedW(SrcReg, MRI, FixableDefs)) + // If all users only use the lower bits, this sext.w is redundant. + // Or if all definitions reaching MI sign-extend their output, + // then sext.w is redundant. + if (!hasAllWUsers(*MI, MRI) && !isSignExtendedW(SrcReg, MRI, FixableDefs)) continue; Register DstReg = MI->getOperand(0).getReg(); diff --git a/llvm/test/CodeGen/RISCV/sextw-removal.ll b/llvm/test/CodeGen/RISCV/sextw-removal.ll index ffc441983840..daa1114b429e 100644 --- a/llvm/test/CodeGen/RISCV/sextw-removal.ll +++ b/llvm/test/CodeGen/RISCV/sextw-removal.ll @@ -1,9 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+f,+zknh -target-abi=lp64f \ ; RUN: | FileCheck %s --check-prefixes=CHECK,RV64I -; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+zbb,+f,+zknh -target-abi=lp64f \ +; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+zba,+zbb,+f,+zknh -target-abi=lp64f \ ; RUN: | FileCheck %s --check-prefixes=CHECK,RV64ZBB -; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+zbb,+f,+zknh -target-abi=lp64f \ +; RUN: llc < %s -mtriple=riscv64 -mattr=+m,+zba,+zbb,+f,+zknh -target-abi=lp64f \ ; RUN: -riscv-disable-sextw-removal | FileCheck %s --check-prefix=NOREMOVAL define void @test1(i32 signext %arg, i32 signext %arg1) nounwind { @@ -1326,3 +1326,50 @@ bb7: ; preds = %bb2 ret void } declare i64 @llvm.riscv.sha256sig0.i64(i64) + +; The type promotion of %7 forms a sext_inreg, but %7 and %6 are combined to +; form a sh2add. This leaves behind a sext.w that isn't needed. +define signext i32 @sextw_sh2add(i1 zeroext %0, i32* %1, i32 signext %2, i32 signext %3, i32 signext %4) { +; RV64I-LABEL: sextw_sh2add: +; RV64I: # %bb.0: +; RV64I-NEXT: slliw a2, a2, 2 +; RV64I-NEXT: addw a2, a2, a3 +; RV64I-NEXT: beqz a0, .LBB22_2 +; RV64I-NEXT: # %bb.1: +; RV64I-NEXT: sw a2, 0(a1) +; RV64I-NEXT: .LBB22_2: +; RV64I-NEXT: addw a0, a2, a4 +; RV64I-NEXT: ret +; +; RV64ZBB-LABEL: sextw_sh2add: +; RV64ZBB: # %bb.0: +; RV64ZBB-NEXT: sh2add a2, a2, a3 +; RV64ZBB-NEXT: beqz a0, .LBB22_2 +; RV64ZBB-NEXT: # %bb.1: +; RV64ZBB-NEXT: sw a2, 0(a1) +; RV64ZBB-NEXT: .LBB22_2: +; RV64ZBB-NEXT: addw a0, a2, a4 +; RV64ZBB-NEXT: ret +; +; NOREMOVAL-LABEL: sextw_sh2add: +; NOREMOVAL: # %bb.0: +; NOREMOVAL-NEXT: sh2add a2, a2, a3 +; NOREMOVAL-NEXT: sext.w a2, a2 +; NOREMOVAL-NEXT: beqz a0, .LBB22_2 +; NOREMOVAL-NEXT: # %bb.1: +; NOREMOVAL-NEXT: sw a2, 0(a1) +; NOREMOVAL-NEXT: .LBB22_2: +; NOREMOVAL-NEXT: addw a0, a2, a4 +; NOREMOVAL-NEXT: ret + %6 = shl i32 %2, 2 + %7 = add i32 %6, %3 + br i1 %0, label %8, label %9 + +8: ; preds = %5 + store i32 %7, i32* %1, align 4 + br label %9 + +9: ; preds = %5, %8 + %10 = add i32 %7, %4 + ret i32 %10 +}