diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp --- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp +++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp @@ -47,6 +47,12 @@ MachineBasicBlock::iterator MBBI, MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi, unsigned SecondOpcode); + bool expandLoad(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NextMBBI); + bool expandStore(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NextMBBI); bool expandLoadLocalAddress(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineBasicBlock::iterator &NextMBBI); @@ -96,6 +102,19 @@ // expanded instructions for each pseudo is correct in the Size field of the // tablegen definition for the pseudo. switch (MBBI->getOpcode()) { + case RISCV::PseudoLB: + case RISCV::PseudoLBU: + case RISCV::PseudoLH: + case RISCV::PseudoLHU: + case RISCV::PseudoLW: + case RISCV::PseudoLWU: + case RISCV::PseudoLD: + return expandLoad(MBB, MBBI, NextMBBI); + case RISCV::PseudoSB: + case RISCV::PseudoSH: + case RISCV::PseudoSW: + case RISCV::PseudoSD: + return expandStore(MBB, MBBI, NextMBBI); case RISCV::PseudoLLA: return expandLoadLocalAddress(MBB, MBBI, NextMBBI); case RISCV::PseudoLA: @@ -196,6 +215,42 @@ return true; } +bool RISCVExpandPseudo::expandLoad( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NextMBBI) { + MachineInstr &MI = *MBBI; + unsigned SecondOpcode; + switch (MI.getOpcode()) { + case RISCV::PseudoLB: SecondOpcode = RISCV::LB; break; + case RISCV::PseudoLBU: SecondOpcode = RISCV::LBU; break; + case RISCV::PseudoLH: SecondOpcode = RISCV::LH; break; + case RISCV::PseudoLHU: SecondOpcode = RISCV::LHU; break; + case RISCV::PseudoLW: SecondOpcode = RISCV::LW; break; + case RISCV::PseudoLWU: SecondOpcode = RISCV::LWU; break; + case RISCV::PseudoLD: SecondOpcode = RISCV::LD; break; + default: + llvm_unreachable("Unexpected opcode"); + } + return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI, + SecondOpcode); +} + +bool RISCVExpandPseudo::expandStore( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NextMBBI) { + MachineInstr &MI = *MBBI; + unsigned SecondOpcode; + switch (MI.getOpcode()) { + case RISCV::PseudoSW: + SecondOpcode = RISCV::SW; + break; + default: + llvm_unreachable("Unexpected opcode"); + } + MI.eraseFromParent(); // TODO + return true; +} + bool RISCVExpandPseudo::expandLoadLocalAddress( MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineBasicBlock::iterator &NextMBBI) { 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 @@ -2019,11 +2019,23 @@ SDValue Base = N->getOperand(BaseOpIdx); - // If the base is an ADDI, we can merge it in to the load/store. - if (!Base.isMachineOpcode() || Base.getMachineOpcode() != RISCV::ADDI) + if (!Base.isMachineOpcode()) return false; - SDValue ImmOperand = Base.getOperand(1); + // If the base is an ADDI or PseudoLLA, we can merge it in to the load/store. + bool BaseIsAddi; + switch (Base.getMachineOpcode()) { + default: + return false; + case RISCV::ADDI: + BaseIsAddi = true; + break; + case RISCV::PseudoLLA: + BaseIsAddi = false; + break; + } + + SDValue ImmOperand = Base.getOperand(BaseIsAddi ? 1 : 0); uint64_t Offset2 = N->getConstantOperandVal(OffsetOpIdx); if (auto *Const = dyn_cast(ImmOperand)) { @@ -2061,20 +2073,60 @@ return false; } - LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: "); + if (BaseIsAddi) + LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: "); + else + LLVM_DEBUG(dbgs() << "Folding load address into mem-op:\nBase: "); LLVM_DEBUG(Base->dump(CurDAG)); LLVM_DEBUG(dbgs() << "\nN: "); LLVM_DEBUG(N->dump(CurDAG)); LLVM_DEBUG(dbgs() << "\n"); - // Modify the offset operand of the load/store. - if (BaseOpIdx == 0) // Load - CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand, - N->getOperand(2)); - else // Store - CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0), - ImmOperand, N->getOperand(3)); - + if (BaseIsAddi) { + // Modify the offset operand of the load/store. + if (BaseOpIdx == 0) // Load + CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand, + N->getOperand(2)); + else // Store + CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0), + ImmOperand, N->getOperand(3)); + } else { + unsigned Opc; + switch (N->getMachineOpcode()) { + default: + return false; + case RISCV::LB: Opc = RISCV::PseudoLB; break; + case RISCV::LBU: Opc = RISCV::PseudoLBU; break; + case RISCV::LH: Opc = RISCV::PseudoLH; break; + case RISCV::LHU: Opc = RISCV::PseudoLHU; break; + case RISCV::LW: Opc = RISCV::PseudoLW; break; + case RISCV::LWU: Opc = RISCV::PseudoLWU; break; + case RISCV::LD: Opc = RISCV::PseudoLD; break; + // case RISCV::FLH: + // case RISCV::FLW: + // case RISCV::FLD: + case RISCV::SB: Opc = RISCV::PseudoSB; break; + case RISCV::SH: Opc = RISCV::PseudoSH; break; + case RISCV::SW: Opc = RISCV::PseudoSW; break; + case RISCV::SD: Opc = RISCV::PseudoSD; break; + // case RISCV::FSH: + // case RISCV::FSW: + // case RISCV::FSD: + } + if (BaseOpIdx == 0) { // Load + SDNode *PseudoLoad = + CurDAG->getMachineNode(Opc, SDLoc(ImmOperand), + N->getValueType(0), MVT::Other, ImmOperand, N->getOperand(2)); + ReplaceUses(N, PseudoLoad); + } else { + MVT XLenVT = Subtarget->getXLenVT(); + auto TmpOp = CurDAG->getRegister(RISCV::X0, XLenVT); + SDNode *PseudoStore = + CurDAG->getMachineNode(Opc, SDLoc(ImmOperand), + N->getValueType(0), MVT::Other, TmpOp, ImmOperand, N->getOperand(3)); + ReplaceUses(N, PseudoStore); + } + } return true; } diff --git a/llvm/test/CodeGen/RISCV/codemodel-lowering.ll b/llvm/test/CodeGen/RISCV/codemodel-lowering.ll --- a/llvm/test/CodeGen/RISCV/codemodel-lowering.ll +++ b/llvm/test/CodeGen/RISCV/codemodel-lowering.ll @@ -18,8 +18,7 @@ ; RV32I-MEDIUM: # %bb.0: ; RV32I-MEDIUM-NEXT: .LBB0_1: # Label of block must be emitted ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(G) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.LBB0_1) -; RV32I-MEDIUM-NEXT: lw a0, 0(a0) +; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.LBB0_1)(a0) ; RV32I-MEDIUM-NEXT: ret %1 = load volatile i32, i32* @G ret i32 %1 @@ -39,11 +38,6 @@ ; ; RV32I-MEDIUM-LABEL: lower_blockaddress: ; RV32I-MEDIUM: # %bb.0: -; RV32I-MEDIUM-NEXT: .LBB1_1: # Label of block must be emitted -; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(addr) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.LBB1_1) -; RV32I-MEDIUM-NEXT: li a1, 1 -; RV32I-MEDIUM-NEXT: sw a1, 0(a0) ; RV32I-MEDIUM-NEXT: ret store volatile i8* blockaddress(@lower_blockaddress, %block), i8** @addr ret void