//
//===---------------------------------------------------------------------===//
//
-// 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.
//
//===---------------------------------------------------------------------===//
SmallPtrSet<MachineInstr *, 4> 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();
; 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 {
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
+}