diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -198,10 +198,13 @@ // See if we can create this constant as (ADD (SLLI X, 32), X) where X is at // worst an LUI+ADDIW. This will require an extra register, but avoids a // constant pool. + // If we have Zba we can use (ADD_UW X, (SLLI X, 32)) to handle cases where + // low and high 32 bits are the same and bit 31 and 63 are set. if (Seq.size() > 3) { int64_t LoVal = SignExtend64<32>(Imm); int64_t HiVal = SignExtend64<32>(((uint64_t)Imm - (uint64_t)LoVal) >> 32); - if (LoVal == HiVal) { + if (LoVal == HiVal || + (Subtarget.hasStdExtZba() && Lo_32(Imm) == Hi_32(Imm))) { RISCVMatInt::InstSeq SeqLo = RISCVMatInt::generateInstSeq(LoVal, Subtarget.getFeatureBits()); if ((SeqLo.size() + 2) < Seq.size()) { @@ -211,8 +214,9 @@ CurDAG->getMachineNode(RISCV::SLLI, DL, VT, Lo, CurDAG->getTargetConstant(32, DL, VT)), 0); - return SDValue(CurDAG->getMachineNode(RISCV::ADD, DL, VT, Lo, SLLI), - 0); + // Prefer ADD when possible. + unsigned AddOpc = (LoVal == HiVal) ? RISCV::ADD : RISCV::ADD_UW; + return SDValue(CurDAG->getMachineNode(AddOpc, DL, VT, Lo, SLLI), 0); } } } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -4809,10 +4809,13 @@ // Special case. See if we can build the constant as (ADD (SLLI X, 32), X) do // that if it will avoid a constant pool. // It will require an extra temporary register though. + // If we have Zba we can use (ADD_UW X, (SLLI X, 32)) to handle cases where + // low and high 32 bits are the same and bit 31 and 63 are set. if (!DAG.shouldOptForSize()) { int64_t LoVal = SignExtend64<32>(Imm); int64_t HiVal = SignExtend64<32>(((uint64_t)Imm - (uint64_t)LoVal) >> 32); - if (LoVal == HiVal) { + if (LoVal == HiVal || + (Subtarget.hasStdExtZba() && Lo_32(Imm) == Hi_32(Imm))) { RISCVMatInt::InstSeq SeqLo = RISCVMatInt::generateInstSeq(LoVal, Subtarget.getFeatureBits()); if ((SeqLo.size() + 2) <= Subtarget.getMaxBuildIntsCost()) diff --git a/llvm/test/CodeGen/RISCV/imm.ll b/llvm/test/CodeGen/RISCV/imm.ll --- a/llvm/test/CodeGen/RISCV/imm.ll +++ b/llvm/test/CodeGen/RISCV/imm.ll @@ -3067,3 +3067,72 @@ ; RV64IXTHEADBB-NEXT: ret ret i64 1157442765409226768 ; 0x0101010101010101 } + +; Hi and lo are the same and also negative. +define i64 @imm64_same_lo_hi_negative() nounwind { +; RV32I-LABEL: imm64_same_lo_hi_negative: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a0, 526344 +; RV32I-NEXT: addi a0, a0, 128 +; RV32I-NEXT: mv a1, a0 +; RV32I-NEXT: ret +; +; RV64-NOPOOL-LABEL: imm64_same_lo_hi_negative: +; RV64-NOPOOL: # %bb.0: +; RV64-NOPOOL-NEXT: lui a0, 983297 +; RV64-NOPOOL-NEXT: slli a0, a0, 4 +; RV64-NOPOOL-NEXT: addi a0, a0, 257 +; RV64-NOPOOL-NEXT: slli a0, a0, 16 +; RV64-NOPOOL-NEXT: addi a0, a0, 257 +; RV64-NOPOOL-NEXT: slli a0, a0, 15 +; RV64-NOPOOL-NEXT: addi a0, a0, 128 +; RV64-NOPOOL-NEXT: ret +; +; RV64I-POOL-LABEL: imm64_same_lo_hi_negative: +; RV64I-POOL: # %bb.0: +; RV64I-POOL-NEXT: lui a0, %hi(.LCPI65_0) +; RV64I-POOL-NEXT: ld a0, %lo(.LCPI65_0)(a0) +; RV64I-POOL-NEXT: ret +; +; RV64IZBA-LABEL: imm64_same_lo_hi_negative: +; RV64IZBA: # %bb.0: +; RV64IZBA-NEXT: lui a0, 526344 +; RV64IZBA-NEXT: addiw a0, a0, 128 +; RV64IZBA-NEXT: slli a1, a0, 32 +; RV64IZBA-NEXT: add.uw a0, a0, a1 +; RV64IZBA-NEXT: ret +; +; RV64IZBB-LABEL: imm64_same_lo_hi_negative: +; RV64IZBB: # %bb.0: +; RV64IZBB-NEXT: lui a0, 983297 +; RV64IZBB-NEXT: slli a0, a0, 4 +; RV64IZBB-NEXT: addi a0, a0, 257 +; RV64IZBB-NEXT: slli a0, a0, 16 +; RV64IZBB-NEXT: addi a0, a0, 257 +; RV64IZBB-NEXT: slli a0, a0, 15 +; RV64IZBB-NEXT: addi a0, a0, 128 +; RV64IZBB-NEXT: ret +; +; RV64IZBS-LABEL: imm64_same_lo_hi_negative: +; RV64IZBS: # %bb.0: +; RV64IZBS-NEXT: lui a0, 983297 +; RV64IZBS-NEXT: slli a0, a0, 4 +; RV64IZBS-NEXT: addi a0, a0, 257 +; RV64IZBS-NEXT: slli a0, a0, 16 +; RV64IZBS-NEXT: addi a0, a0, 257 +; RV64IZBS-NEXT: slli a0, a0, 15 +; RV64IZBS-NEXT: addi a0, a0, 128 +; RV64IZBS-NEXT: ret +; +; RV64IXTHEADBB-LABEL: imm64_same_lo_hi_negative: +; RV64IXTHEADBB: # %bb.0: +; RV64IXTHEADBB-NEXT: lui a0, 983297 +; RV64IXTHEADBB-NEXT: slli a0, a0, 4 +; RV64IXTHEADBB-NEXT: addi a0, a0, 257 +; RV64IXTHEADBB-NEXT: slli a0, a0, 16 +; RV64IXTHEADBB-NEXT: addi a0, a0, 257 +; RV64IXTHEADBB-NEXT: slli a0, a0, 15 +; RV64IXTHEADBB-NEXT: addi a0, a0, 128 +; RV64IXTHEADBB-NEXT: ret + ret i64 9259542123273814144 ; 0x8080808080808080 +}