From 2e10671ec743c1ce5b237a6d8aff0c0c074a001d Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 16 Mar 2022 13:57:21 -0700 Subject: [PATCH] [RISCV] Improve detection of when to skip (and (srl x, c2) c1) -> (srli (slli x, c3-c2), c3) isel. We have a special case to skip this transform if c1 is 0xffffffff and x is sext_inreg in order to use sraiw+zext.w. But we were only checking that we have a sext_inreg opcode, not how many bits are being sign extended. This commit adds a check that it is a sext_inreg from i32 so we know for sure that an sraiw can be created. --- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 3 +- llvm/test/CodeGen/RISCV/rv64zba.ll | 64 ++++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index a15a6dd809b4..875bad0d1d49 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -774,7 +774,8 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { // (srli (slli x, c3-c2), c3). // Skip it in order to select sraiw. bool Skip = Subtarget->hasStdExtZba() && C3 == 32 && - X.getOpcode() == ISD::SIGN_EXTEND_INREG; + X.getOpcode() == ISD::SIGN_EXTEND_INREG && + cast(X.getOperand(1))->getVT() == MVT::i32; if (OneUseOrZExtW && !IsANDI && !Skip) { SDNode *SLLI = CurDAG->getMachineNode( RISCV::SLLI, DL, XLenVT, X, diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll index 2b9c1e25eb98..b0b6c726d8d0 100644 --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -2,7 +2,9 @@ ; RUN: llc -mtriple=riscv64 -mattr=+m -verify-machineinstrs < %s \ ; RUN: | FileCheck %s -check-prefix=RV64I ; RUN: llc -mtriple=riscv64 -mattr=+m,+zba -verify-machineinstrs < %s \ -; RUN: | FileCheck %s -check-prefix=RV64ZBA +; RUN: | FileCheck %s -check-prefixes=RV64ZBA,RV64ZBANOZBB +; RUN: llc -mtriple=riscv64 -mattr=+m,+zba,+zbb -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefixes=RV64ZBA,RV64ZBAZBB define i64 @slliuw(i64 %a) nounwind { ; RV64I-LABEL: slliuw: @@ -1155,3 +1157,63 @@ define i64 @addshl64_5_8(i64 %a, i64 %b) { %e = add i64 %c, %d ret i64 %e } + +; Make sure we use sext.h+slli+srli for Zba+Zbb. +; FIXME: The RV64I and Zba only cases can be done with only 3 shifts. +define zeroext i32 @sext_ashr_zext_i8(i8 %a) nounwind { +; RV64I-LABEL: sext_ashr_zext_i8: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 56 +; RV64I-NEXT: srai a0, a0, 56 +; RV64I-NEXT: slli a0, a0, 23 +; RV64I-NEXT: srli a0, a0, 32 +; RV64I-NEXT: ret +; +; RV64ZBANOZBB-LABEL: sext_ashr_zext_i8: +; RV64ZBANOZBB: # %bb.0: +; RV64ZBANOZBB-NEXT: slli a0, a0, 56 +; RV64ZBANOZBB-NEXT: srai a0, a0, 56 +; RV64ZBANOZBB-NEXT: slli a0, a0, 23 +; RV64ZBANOZBB-NEXT: srli a0, a0, 32 +; RV64ZBANOZBB-NEXT: ret +; +; RV64ZBAZBB-LABEL: sext_ashr_zext_i8: +; RV64ZBAZBB: # %bb.0: +; RV64ZBAZBB-NEXT: sext.b a0, a0 +; RV64ZBAZBB-NEXT: slli a0, a0, 23 +; RV64ZBAZBB-NEXT: srli a0, a0, 32 +; RV64ZBAZBB-NEXT: ret + %ext = sext i8 %a to i32 + %1 = ashr i32 %ext, 9 + ret i32 %1 +} + +; Make sure we use sext.h+slli+srli for Zba+Zbb. +; FIXME: The RV64I and Zba only cases can be done with only 3 shifts. +define zeroext i32 @sext_ashr_zext_i16(i16 %a) nounwind { +; RV64I-LABEL: sext_ashr_zext_i16: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 48 +; RV64I-NEXT: srai a0, a0, 48 +; RV64I-NEXT: slli a0, a0, 23 +; RV64I-NEXT: srli a0, a0, 32 +; RV64I-NEXT: ret +; +; RV64ZBANOZBB-LABEL: sext_ashr_zext_i16: +; RV64ZBANOZBB: # %bb.0: +; RV64ZBANOZBB-NEXT: slli a0, a0, 48 +; RV64ZBANOZBB-NEXT: srai a0, a0, 48 +; RV64ZBANOZBB-NEXT: slli a0, a0, 23 +; RV64ZBANOZBB-NEXT: srli a0, a0, 32 +; RV64ZBANOZBB-NEXT: ret +; +; RV64ZBAZBB-LABEL: sext_ashr_zext_i16: +; RV64ZBAZBB: # %bb.0: +; RV64ZBAZBB-NEXT: sext.h a0, a0 +; RV64ZBAZBB-NEXT: slli a0, a0, 23 +; RV64ZBAZBB-NEXT: srli a0, a0, 32 +; RV64ZBAZBB-NEXT: ret + %ext = sext i16 %a to i32 + %1 = ashr i32 %ext, 9 + ret i32 %1 +}