diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -410,6 +410,8 @@ const SelectionDAG &DAG, unsigned Depth) const override; + const Constant *getTargetConstantFromLoad(LoadSDNode *LD) const override; + // This method returns the name of a target specific DAG node. const char *getTargetNodeName(unsigned Opcode) const override; 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 @@ -9382,6 +9382,51 @@ return 1; } +const Constant * +RISCVTargetLowering::getTargetConstantFromLoad(LoadSDNode *Ld) const { + assert(Ld && "Unexpected null LoadSDNode"); + if (!ISD::isNormalLoad(Ld)) + return nullptr; + + SDValue Ptr = Ld->getBasePtr(); + + // Only constant pools with no offset are supported. + auto GetSupportedConstantPool = [](SDValue Ptr) -> ConstantPoolSDNode * { + auto *CNode = dyn_cast(Ptr); + if (!CNode || CNode->isMachineConstantPoolEntry() || + CNode->getOffset() != 0) + return nullptr; + + return CNode; + }; + + // Simple case, LLA. + if (Ptr.getOpcode() == RISCVISD::LLA) { + auto *CNode = GetSupportedConstantPool(Ptr); + if (!CNode || CNode->getTargetFlags() != 0) + return nullptr; + + return CNode->getConstVal(); + } + + // Look for a HI and ADD_LO pair. + if (Ptr.getOpcode() != RISCVISD::ADD_LO || + Ptr.getOperand(0).getOpcode() != RISCVISD::HI) + return nullptr; + + auto *CNodeLo = GetSupportedConstantPool(Ptr.getOperand(1)); + auto *CNodeHi = GetSupportedConstantPool(Ptr.getOperand(0).getOperand(0)); + + if (!CNodeLo || CNodeLo->getTargetFlags() != RISCVII::MO_LO || + !CNodeHi || CNodeHi->getTargetFlags() != RISCVII::MO_HI) + return nullptr; + + if (CNodeLo->getConstVal() != CNodeHi->getConstVal()) + return nullptr; + + return CNodeLo->getConstVal(); +} + static MachineBasicBlock *emitReadCycleWidePseudo(MachineInstr &MI, MachineBasicBlock *BB) { assert(MI.getOpcode() == RISCV::ReadCycleWide && "Unexpected instruction"); diff --git a/llvm/test/CodeGen/RISCV/rv64zbp-intrinsic.ll b/llvm/test/CodeGen/RISCV/rv64zbp-intrinsic.ll --- a/llvm/test/CodeGen/RISCV/rv64zbp-intrinsic.ll +++ b/llvm/test/CodeGen/RISCV/rv64zbp-intrinsic.ll @@ -530,11 +530,8 @@ ; RV64ZBP: # %bb.0: ; RV64ZBP-NEXT: lui a1, %hi(.LCPI54_0) ; RV64ZBP-NEXT: ld a1, %lo(.LCPI54_0)(a1) -; RV64ZBP-NEXT: lui a2, %hi(.LCPI54_1) -; RV64ZBP-NEXT: ld a2, %lo(.LCPI54_1)(a2) ; RV64ZBP-NEXT: or a0, a0, a1 ; RV64ZBP-NEXT: orc32 a0, a0 -; RV64ZBP-NEXT: or a0, a0, a2 ; RV64ZBP-NEXT: ret %tmp = or i64 %a, 72624976668147840 ; 0x102040810204080 %tmp2 = call i64 @llvm.riscv.gorc.i64(i64 %tmp, i64 32) diff --git a/llvm/test/CodeGen/RISCV/rv64zbp.ll b/llvm/test/CodeGen/RISCV/rv64zbp.ll --- a/llvm/test/CodeGen/RISCV/rv64zbp.ll +++ b/llvm/test/CodeGen/RISCV/rv64zbp.ll @@ -1007,20 +1007,19 @@ ; ; RV64ZBP-LABEL: gorc2b_i64: ; RV64ZBP: # %bb.0: -; RV64ZBP-NEXT: lui a1, %hi(.LCPI26_0) -; RV64ZBP-NEXT: ld a1, %lo(.LCPI26_0)(a1) -; RV64ZBP-NEXT: srli a2, a0, 2 -; RV64ZBP-NEXT: and a2, a2, a1 +; RV64ZBP-NEXT: srli a1, a0, 2 +; RV64ZBP-NEXT: or a1, a1, a0 +; RV64ZBP-NEXT: orc2.n a0, a0 +; RV64ZBP-NEXT: lui a2, %hi(.LCPI26_0) +; RV64ZBP-NEXT: ld a2, %lo(.LCPI26_0)(a2) ; RV64ZBP-NEXT: lui a3, %hi(.LCPI26_1) ; RV64ZBP-NEXT: ld a3, %lo(.LCPI26_1)(a3) -; RV64ZBP-NEXT: or a2, a2, a0 -; RV64ZBP-NEXT: orc2.n a0, a0 -; RV64ZBP-NEXT: slli a2, a2, 2 +; RV64ZBP-NEXT: slli a1, a1, 2 +; RV64ZBP-NEXT: and a1, a1, a2 +; RV64ZBP-NEXT: srli a2, a0, 2 ; RV64ZBP-NEXT: and a2, a2, a3 -; RV64ZBP-NEXT: srli a3, a0, 2 -; RV64ZBP-NEXT: and a1, a3, a1 -; RV64ZBP-NEXT: or a0, a1, a0 -; RV64ZBP-NEXT: or a0, a0, a2 +; RV64ZBP-NEXT: or a0, a2, a0 +; RV64ZBP-NEXT: or a0, a0, a1 ; RV64ZBP-NEXT: ret %and1 = shl i64 %a, 2 %shl1 = and i64 %and1, -3689348814741910324