diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp @@ -141,6 +141,30 @@ Res.push_back(RISCVMatInt::Inst(RISCV::ADDI, Lo12)); } +static bool extractRotateInfo(int64_t Val, int& NegImm12, int& Rotate) { + bool Ret = false; + int LeadingOnes = countLeadingOnes((uint64_t)Val); + int TrailingOnes = countTrailingOnes((uint64_t)Val); + // for case: 0xffffff77ffffffff + if (LeadingOnes < 32 && ((64 - LeadingOnes - TrailingOnes) < 12)) { + NegImm12 = ((uint64_t)Val >> TrailingOnes) | (Val << (64 - TrailingOnes)); + Rotate = 64 - TrailingOnes; + Ret = true; + } else { + int UpperTrailingOnes = countTrailingOnes((uint64_t)(Val >> 32)); + int LowerLeadingOnes = countLeadingOnes((uint64_t)(Val << 32)); + // for case: 0xaffffffffffffffa + if (UpperTrailingOnes < 32 && LowerLeadingOnes < 32 && + ((64 - UpperTrailingOnes - LowerLeadingOnes) < 12)) { + NegImm12 = + (Val << (32 - UpperTrailingOnes)) | (((uint64_t)Val >> (32 + UpperTrailingOnes))); + Rotate = 32 - UpperTrailingOnes; + Ret = true; + } + } + return Ret; +} + namespace llvm { namespace RISCVMatInt { InstSeq generateInstSeq(int64_t Val, const FeatureBitset &ActiveFeatures) { @@ -312,6 +336,17 @@ } } + // Perform optimization with rori in the Zbb extension. + if (Res.size() > 2 && ActiveFeatures[RISCV::FeatureStdExtZbb]) { + int NegImm12; + int Rotate; + if(extractRotateInfo(Val, NegImm12, Rotate)){ + RISCVMatInt::InstSeq TmpSeq; + TmpSeq.push_back(RISCVMatInt::Inst(RISCV::ADDI, NegImm12)); + TmpSeq.push_back(RISCVMatInt::Inst(RISCV::RORI, Rotate)); + Res = TmpSeq; + } + } return Res; } diff --git a/llvm/test/CodeGen/RISCV/imm_zbb.ll b/llvm/test/CodeGen/RISCV/imm_zbb.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/imm_zbb.ll @@ -0,0 +1,24 @@ +; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbb \ +; RUN: -verify-machineinstrs < %s | FileCheck %s -check-prefix=RV64IZBB + + +; Materializing constants with zbb + +; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +define dso_local i64 @li_rori_1() local_unnamed_addr #0 { +; RV64IZBB-LABEL: li_rori_1: +; RV64IZBB: # %bb.0: +; RV64IZBB-NEXT: li a0, -18 +; RV64IZBB-NEXT: rori a0, a0, 21 +; RV64IZBB-NEXT: ret + ret i64 -149533581377537 +} +; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +define dso_local i64 @li_rori_2() local_unnamed_addr #0 { +; RV64IZBB-LABEL: li_rori_2: +; RV64IZBB: # %bb.0: +; RV64IZBB-NEXT: li a0, -86 +; RV64IZBB-NEXT: rori a0, a0, 4 +; RV64IZBB-NEXT: ret + ret i64 -5764607523034234886 +}