[PATCH] D130412: [RISCV] Teach RISCVCodeGenPrepare to optimize (zext (abs(i32 X, i1 1))).
Craig Topper via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 22 23:49:01 PDT 2022
craig.topper created this revision.
craig.topper added reviewers: reames, asb, luismarques.
Herald added subscribers: sunshaoce, VincentWu, luke957, StephenFan, vkmr, frasercrmck, evandro, apazos, sameer.abuasal, s.egerton, Jim, benna, psnobl, jocewei, PkmX, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, jrtc27, shiva0217, kito-cheng, niosHD, sabuasal, simoncook, johnrusso, rbar, hiraditya, arichardson.
Herald added a project: All.
craig.topper requested review of this revision.
Herald added subscribers: pcwang-thead, eopXD, MaskRay.
Herald added a project: LLVM.
(abs(i32 X, i1 1) always produces a positive result. The 'i1 1'
means INT_MIN input produces poison. If the result is sign extended,
InstCombine will convert it to zext. This does not produce ideal
code for RISCV.
This patch reverses the zext back to sext which can be folded
into a subw or negw. Ideally we'd do this in SelectionDAG, but
we lose the INT_MIN poison flag when llvm.abs becomes ISD::ABS.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D130412
Files:
llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp
llvm/test/CodeGen/RISCV/iabs.ll
Index: llvm/test/CodeGen/RISCV/iabs.ll
===================================================================
--- llvm/test/CodeGen/RISCV/iabs.ll
+++ llvm/test/CodeGen/RISCV/iabs.ll
@@ -694,3 +694,51 @@
ret i128 %3
}
+define i64 @zext_abs32(i32 %x) {
+; RV32I-LABEL: zext_abs32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: srai a1, a0, 31
+; RV32I-NEXT: xor a0, a0, a1
+; RV32I-NEXT: sub a0, a0, a1
+; RV32I-NEXT: li a1, 0
+; RV32I-NEXT: ret
+;
+; RV32ZBB-LABEL: zext_abs32:
+; RV32ZBB: # %bb.0:
+; RV32ZBB-NEXT: neg a1, a0
+; RV32ZBB-NEXT: max a0, a0, a1
+; RV32ZBB-NEXT: li a1, 0
+; RV32ZBB-NEXT: ret
+;
+; RV32ZBT-LABEL: zext_abs32:
+; RV32ZBT: # %bb.0:
+; RV32ZBT-NEXT: srai a1, a0, 31
+; RV32ZBT-NEXT: xor a0, a0, a1
+; RV32ZBT-NEXT: sub a0, a0, a1
+; RV32ZBT-NEXT: li a1, 0
+; RV32ZBT-NEXT: ret
+;
+; RV64I-LABEL: zext_abs32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: sraiw a1, a0, 31
+; RV64I-NEXT: xor a0, a0, a1
+; RV64I-NEXT: subw a0, a0, a1
+; RV64I-NEXT: ret
+;
+; RV64ZBB-LABEL: zext_abs32:
+; RV64ZBB: # %bb.0:
+; RV64ZBB-NEXT: sext.w a0, a0
+; RV64ZBB-NEXT: negw a1, a0
+; RV64ZBB-NEXT: max a0, a0, a1
+; RV64ZBB-NEXT: ret
+;
+; RV64ZBT-LABEL: zext_abs32:
+; RV64ZBT: # %bb.0:
+; RV64ZBT-NEXT: sraiw a1, a0, 31
+; RV64ZBT-NEXT: xor a0, a0, a1
+; RV64ZBT-NEXT: subw a0, a0, a1
+; RV64ZBT-NEXT: ret
+ %abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
+ %zext = zext i32 %abs to i64
+ ret i64 %zext
+}
Index: llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp
===================================================================
--- llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp
+++ llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
@@ -81,6 +82,20 @@
return true;
}
+ // Convert (zext (abs(i32 X, i1 1))) -> (sext (abs(i32 X, i1 1))). If abs of
+ // INT_MIN is poison, the sign bit is zero.
+ using namespace PatternMatch;
+ if (match(Src, m_Intrinsic<Intrinsic::abs>(m_Value(), m_One()))) {
+ auto *SExt = new SExtInst(Src, ZExt->getType(), "", ZExt);
+ SExt->takeName(ZExt);
+ SExt->setDebugLoc(ZExt->getDebugLoc());
+
+ ZExt->replaceAllUsesWith(SExt);
+ ZExt->eraseFromParent();
+ ++NumZExtToSExt;
+ return true;
+ }
+
return false;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D130412.447042.patch
Type: text/x-patch
Size: 2521 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220723/a954ca35/attachment.bin>
More information about the llvm-commits
mailing list