diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp --- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp +++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -237,7 +237,7 @@ // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand). if (!AddrReg.isReg()) return true; - if (!Offset.isImm() && !Offset.isGlobal()) + if (!Offset.isImm() && !Offset.isGlobal() && !Offset.isMCSymbol()) return true; MCOperand MCO; @@ -246,7 +246,7 @@ if (Offset.isImm()) OS << MCO.getImm(); - else if (Offset.isGlobal()) + else if (Offset.isGlobal() || Offset.isMCSymbol()) OS << *MCO.getExpr(); OS << "(" << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")"; return false; diff --git a/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp b/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp --- a/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp +++ b/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp @@ -29,6 +29,7 @@ class RISCVMergeBaseOffsetOpt : public MachineFunctionPass { const RISCVSubtarget *ST = nullptr; MachineRegisterInfo *MRI; + const RISCVInstrInfo *TII; public: static char ID; @@ -357,6 +358,7 @@ // Tail: lw vreg3, 8(vreg2) std::optional CommonOffset; + SmallVector InlineAsmMemoryOpIndexes; for (const MachineInstr &UseMI : MRI->use_instructions(DestReg)) { switch (UseMI.getOpcode()) { default: @@ -391,6 +393,40 @@ if (CommonOffset && Offset != CommonOffset) return false; CommonOffset = Offset; + break; + } + case RISCV::INLINEASM: { + unsigned NumOps = 0; + for (unsigned I = InlineAsm::MIOp_FirstOperand; + I < UseMI.getNumOperands(); I += 1 + NumOps) { + MachineOperand FlagsMO = UseMI.getOperand(I); + // Should be an imm. + if (!FlagsMO.isImm()) + continue; + + unsigned Flags = FlagsMO.getImm(); + NumOps = InlineAsm::getNumOperandRegisters(Flags); + + // Memory constraints have two operands. + if (NumOps != 2 || !InlineAsm::isMemKind(Flags)) + continue; + + auto AddrMO = UseMI.getOperand(I + 1); + if (!AddrMO.isReg() || AddrMO.getReg() != DestReg) + continue; + + auto OffsetMO = UseMI.getOperand(I + 2); + if (!OffsetMO.isImm()) + continue; + + // All inline asm memory operands must use the same offset. + int64_t Offset = OffsetMO.getImm(); + if (CommonOffset && Offset != CommonOffset) + return false; + CommonOffset = Offset; + InlineAsmMemoryOpIndexes.push_back(I + 1); + } + break; } } } @@ -415,13 +451,26 @@ // Update the immediate in the load/store instructions to add the offset. for (MachineInstr &UseMI : llvm::make_early_inc_range(MRI->use_instructions(DestReg))) { - UseMI.removeOperand(2); - UseMI.addOperand(ImmOp); - // Update the base reg in the Tail instruction to feed from LUI. - // Output of Hi is only used in Lo, no need to use MRI->replaceRegWith(). - UseMI.getOperand(1).setReg(Hi.getOperand(0).getReg()); + if (UseMI.getOpcode() == RISCV::INLINEASM) { + auto NewMI = BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(), + TII->get(RISCV::INLINEASM)); + for (unsigned I = 0; I < UseMI.getNumOperands(); I++) { + if (!llvm::is_contained(InlineAsmMemoryOpIndexes, I)) { + NewMI->addOperand(UseMI.getOperand(I)); + continue; + } + NewMI->addOperand(UseMI.getOperand(I)); + NewMI->addOperand(ImmOp); + I++; + } + UseMI.removeFromParent(); + } else { + UseMI.removeOperand(2); + UseMI.addOperand(ImmOp); + } } + MRI->replaceRegWith(Lo.getOperand(0).getReg(), Hi.getOperand(0).getReg()); Lo.eraseFromParent(); return true; } @@ -431,6 +480,7 @@ return false; ST = &Fn.getSubtarget(); + TII = ST->getInstrInfo(); bool MadeChange = false; MRI = &Fn.getRegInfo(); diff --git a/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll b/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll --- a/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll @@ -125,9 +125,8 @@ ; RV32I-MEDIUM: # %bb.0: ; RV32I-MEDIUM-NEXT: .Lpcrel_hi0: ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi0) ; RV32I-MEDIUM-NEXT: #APP -; RV32I-MEDIUM-NEXT: sw zero, 0(a0) +; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi0)(a0) ; RV32I-MEDIUM-NEXT: #NO_APP ; RV32I-MEDIUM-NEXT: ret ; @@ -135,9 +134,8 @@ ; RV64I-MEDIUM: # %bb.0: ; RV64I-MEDIUM-NEXT: .Lpcrel_hi0: ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi0) ; RV64I-MEDIUM-NEXT: #APP -; RV64I-MEDIUM-NEXT: sw zero, 0(a0) +; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi0)(a0) ; RV64I-MEDIUM-NEXT: #NO_APP ; RV64I-MEDIUM-NEXT: ret call void asm "sw zero, $0", "=*m"(ptr elementtype(i32) @eg) @@ -147,39 +145,35 @@ define void @constraint_m_with_global_2() nounwind { ; RV32I-LABEL: constraint_m_with_global_2: ; RV32I: # %bb.0: -; RV32I-NEXT: lui a0, %hi(eg) -; RV32I-NEXT: addi a0, a0, %lo(eg) +; RV32I-NEXT: lui a0, %hi(eg+4) ; RV32I-NEXT: #APP -; RV32I-NEXT: sw zero, 4(a0) +; RV32I-NEXT: sw zero, %lo(eg+4)(a0) ; RV32I-NEXT: #NO_APP ; RV32I-NEXT: ret ; ; RV64I-LABEL: constraint_m_with_global_2: ; RV64I: # %bb.0: -; RV64I-NEXT: lui a0, %hi(eg) -; RV64I-NEXT: addi a0, a0, %lo(eg) +; RV64I-NEXT: lui a0, %hi(eg+4) ; RV64I-NEXT: #APP -; RV64I-NEXT: sw zero, 4(a0) +; RV64I-NEXT: sw zero, %lo(eg+4)(a0) ; RV64I-NEXT: #NO_APP ; RV64I-NEXT: ret ; ; RV32I-MEDIUM-LABEL: constraint_m_with_global_2: ; RV32I-MEDIUM: # %bb.0: ; RV32I-MEDIUM-NEXT: .Lpcrel_hi1: -; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi1) +; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg+4) ; RV32I-MEDIUM-NEXT: #APP -; RV32I-MEDIUM-NEXT: sw zero, 4(a0) +; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi1)(a0) ; RV32I-MEDIUM-NEXT: #NO_APP ; RV32I-MEDIUM-NEXT: ret ; ; RV64I-MEDIUM-LABEL: constraint_m_with_global_2: ; RV64I-MEDIUM: # %bb.0: ; RV64I-MEDIUM-NEXT: .Lpcrel_hi1: -; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi1) +; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg+4) ; RV64I-MEDIUM-NEXT: #APP -; RV64I-MEDIUM-NEXT: sw zero, 4(a0) +; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi1)(a0) ; RV64I-MEDIUM-NEXT: #NO_APP ; RV64I-MEDIUM-NEXT: ret call void asm "sw zero, $0", "=*m"(ptr nonnull elementtype(i32) getelementptr inbounds ([400000 x i32], ptr @eg, i32 0, i32 1)) @@ -190,18 +184,16 @@ ; RV32I-LABEL: constraint_m_with_global_3: ; RV32I: # %bb.0: ; RV32I-NEXT: lui a0, %hi(eg+8000) -; RV32I-NEXT: addi a0, a0, %lo(eg+8000) ; RV32I-NEXT: #APP -; RV32I-NEXT: sw zero, 0(a0) +; RV32I-NEXT: sw zero, %lo(eg+8000)(a0) ; RV32I-NEXT: #NO_APP ; RV32I-NEXT: ret ; ; RV64I-LABEL: constraint_m_with_global_3: ; RV64I: # %bb.0: ; RV64I-NEXT: lui a0, %hi(eg+8000) -; RV64I-NEXT: addi a0, a0, %lo(eg+8000) ; RV64I-NEXT: #APP -; RV64I-NEXT: sw zero, 0(a0) +; RV64I-NEXT: sw zero, %lo(eg+8000)(a0) ; RV64I-NEXT: #NO_APP ; RV64I-NEXT: ret ; @@ -209,9 +201,8 @@ ; RV32I-MEDIUM: # %bb.0: ; RV32I-MEDIUM-NEXT: .Lpcrel_hi2: ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg+8000) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi2) ; RV32I-MEDIUM-NEXT: #APP -; RV32I-MEDIUM-NEXT: sw zero, 0(a0) +; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi2)(a0) ; RV32I-MEDIUM-NEXT: #NO_APP ; RV32I-MEDIUM-NEXT: ret ; @@ -219,9 +210,8 @@ ; RV64I-MEDIUM: # %bb.0: ; RV64I-MEDIUM-NEXT: .Lpcrel_hi2: ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg+8000) -; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi2) ; RV64I-MEDIUM-NEXT: #APP -; RV64I-MEDIUM-NEXT: sw zero, 0(a0) +; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi2)(a0) ; RV64I-MEDIUM-NEXT: #NO_APP ; RV64I-MEDIUM-NEXT: ret call void asm "sw zero, $0", "=*m"(ptr nonnull elementtype(i32) getelementptr inbounds ([400000 x i32], ptr @eg, i32 0, i32 2000)) @@ -271,19 +261,17 @@ define void @constraint_m_with_extern_weak_global_2() nounwind { ; RV32I-LABEL: constraint_m_with_extern_weak_global_2: ; RV32I: # %bb.0: -; RV32I-NEXT: lui a0, %hi(ewg) -; RV32I-NEXT: addi a0, a0, %lo(ewg) +; RV32I-NEXT: lui a0, %hi(ewg+4) ; RV32I-NEXT: #APP -; RV32I-NEXT: sw zero, 4(a0) +; RV32I-NEXT: sw zero, %lo(ewg+4)(a0) ; RV32I-NEXT: #NO_APP ; RV32I-NEXT: ret ; ; RV64I-LABEL: constraint_m_with_extern_weak_global_2: ; RV64I: # %bb.0: -; RV64I-NEXT: lui a0, %hi(ewg) -; RV64I-NEXT: addi a0, a0, %lo(ewg) +; RV64I-NEXT: lui a0, %hi(ewg+4) ; RV64I-NEXT: #APP -; RV64I-NEXT: sw zero, 4(a0) +; RV64I-NEXT: sw zero, %lo(ewg+4)(a0) ; RV64I-NEXT: #NO_APP ; RV64I-NEXT: ret ; @@ -314,18 +302,16 @@ ; RV32I-LABEL: constraint_m_with_extern_weak_global_3: ; RV32I: # %bb.0: ; RV32I-NEXT: lui a0, %hi(ewg+8000) -; RV32I-NEXT: addi a0, a0, %lo(ewg+8000) ; RV32I-NEXT: #APP -; RV32I-NEXT: sw zero, 0(a0) +; RV32I-NEXT: sw zero, %lo(ewg+8000)(a0) ; RV32I-NEXT: #NO_APP ; RV32I-NEXT: ret ; ; RV64I-LABEL: constraint_m_with_extern_weak_global_3: ; RV64I: # %bb.0: ; RV64I-NEXT: lui a0, %hi(ewg+8000) -; RV64I-NEXT: addi a0, a0, %lo(ewg+8000) ; RV64I-NEXT: #APP -; RV64I-NEXT: sw zero, 0(a0) +; RV64I-NEXT: sw zero, %lo(ewg+8000)(a0) ; RV64I-NEXT: #NO_APP ; RV64I-NEXT: ret ; @@ -472,9 +458,8 @@ ; RV32I-MEDIUM: # %bb.0: ; RV32I-MEDIUM-NEXT: .Lpcrel_hi6: ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi6) ; RV32I-MEDIUM-NEXT: #APP -; RV32I-MEDIUM-NEXT: sw zero, 0(a0) +; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi6)(a0) ; RV32I-MEDIUM-NEXT: #NO_APP ; RV32I-MEDIUM-NEXT: ret ; @@ -482,9 +467,8 @@ ; RV64I-MEDIUM: # %bb.0: ; RV64I-MEDIUM-NEXT: .Lpcrel_hi6: ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi6) ; RV64I-MEDIUM-NEXT: #APP -; RV64I-MEDIUM-NEXT: sw zero, 0(a0) +; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi6)(a0) ; RV64I-MEDIUM-NEXT: #NO_APP ; RV64I-MEDIUM-NEXT: ret call void asm "sw zero, $0", "=*o"(ptr elementtype(i32) @eg) @@ -494,39 +478,35 @@ define void @constraint_o_with_global_2() nounwind { ; RV32I-LABEL: constraint_o_with_global_2: ; RV32I: # %bb.0: -; RV32I-NEXT: lui a0, %hi(eg) -; RV32I-NEXT: addi a0, a0, %lo(eg) +; RV32I-NEXT: lui a0, %hi(eg+4) ; RV32I-NEXT: #APP -; RV32I-NEXT: sw zero, 4(a0) +; RV32I-NEXT: sw zero, %lo(eg+4)(a0) ; RV32I-NEXT: #NO_APP ; RV32I-NEXT: ret ; ; RV64I-LABEL: constraint_o_with_global_2: ; RV64I: # %bb.0: -; RV64I-NEXT: lui a0, %hi(eg) -; RV64I-NEXT: addi a0, a0, %lo(eg) +; RV64I-NEXT: lui a0, %hi(eg+4) ; RV64I-NEXT: #APP -; RV64I-NEXT: sw zero, 4(a0) +; RV64I-NEXT: sw zero, %lo(eg+4)(a0) ; RV64I-NEXT: #NO_APP ; RV64I-NEXT: ret ; ; RV32I-MEDIUM-LABEL: constraint_o_with_global_2: ; RV32I-MEDIUM: # %bb.0: ; RV32I-MEDIUM-NEXT: .Lpcrel_hi7: -; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi7) +; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg+4) ; RV32I-MEDIUM-NEXT: #APP -; RV32I-MEDIUM-NEXT: sw zero, 4(a0) +; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi7)(a0) ; RV32I-MEDIUM-NEXT: #NO_APP ; RV32I-MEDIUM-NEXT: ret ; ; RV64I-MEDIUM-LABEL: constraint_o_with_global_2: ; RV64I-MEDIUM: # %bb.0: ; RV64I-MEDIUM-NEXT: .Lpcrel_hi7: -; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi7) +; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg+4) ; RV64I-MEDIUM-NEXT: #APP -; RV64I-MEDIUM-NEXT: sw zero, 4(a0) +; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi7)(a0) ; RV64I-MEDIUM-NEXT: #NO_APP ; RV64I-MEDIUM-NEXT: ret call void asm "sw zero, $0", "=*o"(ptr nonnull elementtype(i32) getelementptr inbounds ([400000 x i32], ptr @eg, i32 0, i32 1)) @@ -537,18 +517,16 @@ ; RV32I-LABEL: constraint_o_with_global_3: ; RV32I: # %bb.0: ; RV32I-NEXT: lui a0, %hi(eg+8000) -; RV32I-NEXT: addi a0, a0, %lo(eg+8000) ; RV32I-NEXT: #APP -; RV32I-NEXT: sw zero, 0(a0) +; RV32I-NEXT: sw zero, %lo(eg+8000)(a0) ; RV32I-NEXT: #NO_APP ; RV32I-NEXT: ret ; ; RV64I-LABEL: constraint_o_with_global_3: ; RV64I: # %bb.0: ; RV64I-NEXT: lui a0, %hi(eg+8000) -; RV64I-NEXT: addi a0, a0, %lo(eg+8000) ; RV64I-NEXT: #APP -; RV64I-NEXT: sw zero, 0(a0) +; RV64I-NEXT: sw zero, %lo(eg+8000)(a0) ; RV64I-NEXT: #NO_APP ; RV64I-NEXT: ret ; @@ -556,9 +534,8 @@ ; RV32I-MEDIUM: # %bb.0: ; RV32I-MEDIUM-NEXT: .Lpcrel_hi8: ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg+8000) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi8) ; RV32I-MEDIUM-NEXT: #APP -; RV32I-MEDIUM-NEXT: sw zero, 0(a0) +; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi8)(a0) ; RV32I-MEDIUM-NEXT: #NO_APP ; RV32I-MEDIUM-NEXT: ret ; @@ -566,9 +543,8 @@ ; RV64I-MEDIUM: # %bb.0: ; RV64I-MEDIUM-NEXT: .Lpcrel_hi8: ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg+8000) -; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi8) ; RV64I-MEDIUM-NEXT: #APP -; RV64I-MEDIUM-NEXT: sw zero, 0(a0) +; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi8)(a0) ; RV64I-MEDIUM-NEXT: #NO_APP ; RV64I-MEDIUM-NEXT: ret call void asm "sw zero, $0", "=*o"(ptr nonnull elementtype(i32) getelementptr inbounds ([400000 x i32], ptr @eg, i32 0, i32 2000)) @@ -618,19 +594,17 @@ define void @constraint_o_with_extern_weak_global_2() nounwind { ; RV32I-LABEL: constraint_o_with_extern_weak_global_2: ; RV32I: # %bb.0: -; RV32I-NEXT: lui a0, %hi(ewg) -; RV32I-NEXT: addi a0, a0, %lo(ewg) +; RV32I-NEXT: lui a0, %hi(ewg+4) ; RV32I-NEXT: #APP -; RV32I-NEXT: sw zero, 4(a0) +; RV32I-NEXT: sw zero, %lo(ewg+4)(a0) ; RV32I-NEXT: #NO_APP ; RV32I-NEXT: ret ; ; RV64I-LABEL: constraint_o_with_extern_weak_global_2: ; RV64I: # %bb.0: -; RV64I-NEXT: lui a0, %hi(ewg) -; RV64I-NEXT: addi a0, a0, %lo(ewg) +; RV64I-NEXT: lui a0, %hi(ewg+4) ; RV64I-NEXT: #APP -; RV64I-NEXT: sw zero, 4(a0) +; RV64I-NEXT: sw zero, %lo(ewg+4)(a0) ; RV64I-NEXT: #NO_APP ; RV64I-NEXT: ret ; @@ -661,18 +635,16 @@ ; RV32I-LABEL: constraint_o_with_extern_weak_global_3: ; RV32I: # %bb.0: ; RV32I-NEXT: lui a0, %hi(ewg+8000) -; RV32I-NEXT: addi a0, a0, %lo(ewg+8000) ; RV32I-NEXT: #APP -; RV32I-NEXT: sw zero, 0(a0) +; RV32I-NEXT: sw zero, %lo(ewg+8000)(a0) ; RV32I-NEXT: #NO_APP ; RV32I-NEXT: ret ; ; RV64I-LABEL: constraint_o_with_extern_weak_global_3: ; RV64I: # %bb.0: ; RV64I-NEXT: lui a0, %hi(ewg+8000) -; RV64I-NEXT: addi a0, a0, %lo(ewg+8000) ; RV64I-NEXT: #APP -; RV64I-NEXT: sw zero, 0(a0) +; RV64I-NEXT: sw zero, %lo(ewg+8000)(a0) ; RV64I-NEXT: #NO_APP ; RV64I-NEXT: ret ;