[llvm] 1db6d6d - [RISCV] Teach RISCVCodeGenPrepare to optimize (zext (abs(i32 X, i1 1))).

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 25 09:37:07 PDT 2022


Author: Craig Topper
Date: 2022-07-25T09:36:41-07:00
New Revision: 1db6d6dcd888540574e5ada6dadc09029e5e79ec

URL: https://github.com/llvm/llvm-project/commit/1db6d6dcd888540574e5ada6dadc09029e5e79ec
DIFF: https://github.com/llvm/llvm-project/commit/1db6d6dcd888540574e5ada6dadc09029e5e79ec.diff

LOG: [RISCV] Teach RISCVCodeGenPrepare to optimize (zext (abs(i32 X, i1 1))).

(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.

Reviewed By: reames

Differential Revision: https://reviews.llvm.org/D130412

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp
    llvm/test/CodeGen/RISCV/iabs.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp b/llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp
index b700a9ede39ba..a19253da440e7 100644
--- a/llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp
+++ b/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 @@ bool RISCVCodeGenPrepare::optimizeZExt(ZExtInst *ZExt) {
     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;
 }
 

diff  --git a/llvm/test/CodeGen/RISCV/iabs.ll b/llvm/test/CodeGen/RISCV/iabs.ll
index 749887d9e0e0f..8434f886624c0 100644
--- a/llvm/test/CodeGen/RISCV/iabs.ll
+++ b/llvm/test/CodeGen/RISCV/iabs.ll
@@ -694,3 +694,51 @@ define i128 @select_abs128(i128 %x) {
   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
+}


        


More information about the llvm-commits mailing list