From 00341691ac31795b2d6fd5849efc586dd57dd40e Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 26 Jul 2024 17:11:01 -0700 Subject: [PATCH] [RISCV] Don't crash in RISCVMergeBaseOffset if INLINE_ASM uses address register in a non-memory constraint. (#100790) If the register is used by a non-memory constraint we should disable the fold. Otherwise, we may leave CommonOffset unassigned. Fixes #100779. (cherry picked from commit c901b739b67476b00209b7ee706de94c0595d763) --- .../lib/Target/RISCV/RISCVMergeBaseOffset.cpp | 10 +++- .../RISCV/inline-asm-mem-constraint.ll | 50 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp b/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp index fecc83a821f420..b6ac3384e7d3ee 100644 --- a/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp +++ b/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp @@ -429,8 +429,16 @@ bool RISCVMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi, NumOps = Flags.getNumOperandRegisters(); // Memory constraints have two operands. - if (NumOps != 2 || !Flags.isMemKind()) + if (NumOps != 2 || !Flags.isMemKind()) { + // If the register is used by something other than a memory contraint, + // we should not fold. + for (unsigned J = 0; J < NumOps; ++J) { + const MachineOperand &MO = UseMI.getOperand(I + 1 + J); + if (MO.isReg() && MO.getReg() == DestReg) + return false; + } continue; + } // We can't do this for constraint A because AMO instructions don't have // an immediate offset field. diff --git a/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll b/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll index 52d0dabf18839d..6666d92feaac2e 100644 --- a/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll @@ -2252,3 +2252,53 @@ label: call void asm "lw zero, $0", "*A"(ptr elementtype(i32) getelementptr (i8, ptr blockaddress(@constraint_A_with_local_3, %label), i32 2000)) ret void } + +@_ZN5repro9MY_BUFFER17hb0f674501d5980a6E = external global <{ [16 x i8] }> + +; Address is not used by a memory constraint. +define void @should_not_fold() { +; RV32I-LABEL: should_not_fold: +; RV32I: # %bb.0: # %start +; RV32I-NEXT: .cfi_def_cfa_offset 0 +; RV32I-NEXT: lui a0, %hi(_ZN5repro9MY_BUFFER17hb0f674501d5980a6E) +; RV32I-NEXT: addi a0, a0, %lo(_ZN5repro9MY_BUFFER17hb0f674501d5980a6E) +; RV32I-NEXT: #APP +; RV32I-NEXT: ecall +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: should_not_fold: +; RV64I: # %bb.0: # %start +; RV64I-NEXT: .cfi_def_cfa_offset 0 +; RV64I-NEXT: lui a0, %hi(_ZN5repro9MY_BUFFER17hb0f674501d5980a6E) +; RV64I-NEXT: addi a0, a0, %lo(_ZN5repro9MY_BUFFER17hb0f674501d5980a6E) +; RV64I-NEXT: #APP +; RV64I-NEXT: ecall +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret +; +; RV32I-MEDIUM-LABEL: should_not_fold: +; RV32I-MEDIUM: # %bb.0: # %start +; RV32I-MEDIUM-NEXT: .cfi_def_cfa_offset 0 +; RV32I-MEDIUM-NEXT: .Lpcrel_hi39: +; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(_ZN5repro9MY_BUFFER17hb0f674501d5980a6E) +; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi39) +; RV32I-MEDIUM-NEXT: #APP +; RV32I-MEDIUM-NEXT: ecall +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: ret +; +; RV64I-MEDIUM-LABEL: should_not_fold: +; RV64I-MEDIUM: # %bb.0: # %start +; RV64I-MEDIUM-NEXT: .cfi_def_cfa_offset 0 +; RV64I-MEDIUM-NEXT: .Lpcrel_hi39: +; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(_ZN5repro9MY_BUFFER17hb0f674501d5980a6E) +; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi39) +; RV64I-MEDIUM-NEXT: #APP +; RV64I-MEDIUM-NEXT: ecall +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: ret +start: + %0 = tail call ptr asm sideeffect alignstack "ecall", "=&{x10},0,~{vtype},~{vl},~{vxsat},~{vxrm},~{memory}"(ptr @_ZN5repro9MY_BUFFER17hb0f674501d5980a6E) + ret void +}