aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/RISCV/RISCVSExtWRemoval.cpp11
-rw-r--r--llvm/test/CodeGen/RISCV/sextw-removal.ll51
2 files changed, 56 insertions, 6 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVSExtWRemoval.cpp b/llvm/lib/Target/RISCV/RISCVSExtWRemoval.cpp
index 113a493..73b9d67 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<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();
diff --git a/llvm/test/CodeGen/RISCV/sextw-removal.ll b/llvm/test/CodeGen/RISCV/sextw-removal.ll
index ffc4419..daa1114 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
+}