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 @@ -358,6 +358,266 @@ ret void } +define void @constraint_m_with_multi_operands() nounwind { +; RV32I-LABEL: constraint_m_with_multi_operands: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a0, %hi(eg) +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a0); sw zero, %lo(eg)(a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: constraint_m_with_multi_operands: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a0, %hi(eg) +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a0); sw zero, %lo(eg)(a0) +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret +; +; RV32I-MEDIUM-LABEL: constraint_m_with_multi_operands: +; 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); sw zero, 0(a0) +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: ret +; +; RV64I-MEDIUM-LABEL: constraint_m_with_multi_operands: +; 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); sw zero, 0(a0) +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: ret + call void asm "sw zero, $0; sw zero, $1", "=*m,=*m"(ptr elementtype(i32) @eg, ptr elementtype(i32) @eg) + ret void +} + +define void @constraint_m_with_multi_asm() nounwind { +; RV32I-LABEL: constraint_m_with_multi_asm: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a0, %hi(eg) +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: constraint_m_with_multi_asm: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a0, %hi(eg) +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a0) +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a0) +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret +; +; RV32I-MEDIUM-LABEL: constraint_m_with_multi_asm: +; 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: #APP +; RV32I-MEDIUM-NEXT: sw zero, 0(a0) +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: #APP +; RV32I-MEDIUM-NEXT: sw zero, 0(a0) +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: ret +; +; RV64I-MEDIUM-LABEL: constraint_m_with_multi_asm: +; 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: #APP +; RV64I-MEDIUM-NEXT: sw zero, 0(a0) +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: #APP +; RV64I-MEDIUM-NEXT: sw zero, 0(a0) +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: ret + call void asm "sw zero, $0", "=*m"(ptr elementtype(i32) @eg) + call void asm "sw zero, $0", "=*m"(ptr elementtype(i32) @eg) + ret void +} + +define i32 @constraint_m_with_callbr_multi_operands(i32 %a) { +; RV32I-LABEL: constraint_m_with_callbr_multi_operands: +; RV32I: # %bb.0: # %entry +; RV32I-NEXT: lui a1, %hi(eg) +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a1); sw zero, %lo(eg)(a1); beqz a0, .LBB11_2 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: # %bb.1: # %normal +; RV32I-NEXT: li a0, 0 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB11_2: # Block address taken +; RV32I-NEXT: # %fail +; RV32I-NEXT: # Label of block must be emitted +; RV32I-NEXT: li a0, 1 +; RV32I-NEXT: ret +; +; RV64I-LABEL: constraint_m_with_callbr_multi_operands: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: lui a1, %hi(eg) +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a1); sw zero, %lo(eg)(a1); beqz a0, .LBB11_2 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: # %bb.1: # %normal +; RV64I-NEXT: li a0, 0 +; RV64I-NEXT: ret +; RV64I-NEXT: .LBB11_2: # Block address taken +; RV64I-NEXT: # %fail +; RV64I-NEXT: # Label of block must be emitted +; RV64I-NEXT: li a0, 1 +; RV64I-NEXT: ret +; +; RV32I-MEDIUM-LABEL: constraint_m_with_callbr_multi_operands: +; RV32I-MEDIUM: # %bb.0: # %entry +; RV32I-MEDIUM-NEXT: .Lpcrel_hi8: +; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg) +; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi8) +; RV32I-MEDIUM-NEXT: #APP +; RV32I-MEDIUM-NEXT: sw zero, 0(a1); sw zero, 0(a1); beqz a0, .LBB11_2 +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: # %bb.1: # %normal +; RV32I-MEDIUM-NEXT: li a0, 0 +; RV32I-MEDIUM-NEXT: ret +; RV32I-MEDIUM-NEXT: .LBB11_2: # Block address taken +; RV32I-MEDIUM-NEXT: # %fail +; RV32I-MEDIUM-NEXT: # Label of block must be emitted +; RV32I-MEDIUM-NEXT: li a0, 1 +; RV32I-MEDIUM-NEXT: ret +; +; RV64I-MEDIUM-LABEL: constraint_m_with_callbr_multi_operands: +; RV64I-MEDIUM: # %bb.0: # %entry +; RV64I-MEDIUM-NEXT: .Lpcrel_hi8: +; RV64I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg) +; RV64I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi8) +; RV64I-MEDIUM-NEXT: #APP +; RV64I-MEDIUM-NEXT: sw zero, 0(a1); sw zero, 0(a1); beqz a0, .LBB11_2 +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: # %bb.1: # %normal +; RV64I-MEDIUM-NEXT: li a0, 0 +; RV64I-MEDIUM-NEXT: ret +; RV64I-MEDIUM-NEXT: .LBB11_2: # Block address taken +; RV64I-MEDIUM-NEXT: # %fail +; RV64I-MEDIUM-NEXT: # Label of block must be emitted +; RV64I-MEDIUM-NEXT: li a0, 1 +; RV64I-MEDIUM-NEXT: ret +entry: + callbr void asm "sw zero, $0; sw zero, $1; beqz $2, $3", "=*m,=*m,r,!i"(ptr elementtype(i32) @eg, ptr elementtype(i32) @eg, i32 %a) to label %normal [label %fail] + +normal: + ret i32 0 + +fail: + ret i32 1 +} + +define i32 @constraint_m_with_multi_callbr_asm(i32 %a) { +; RV32I-LABEL: constraint_m_with_multi_callbr_asm: +; RV32I: # %bb.0: # %entry +; RV32I-NEXT: lui a1, %hi(eg) +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a1); beqz a0, .LBB12_3 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: # %bb.1: # %normal0 +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a1); beqz a0, .LBB12_3 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: # %bb.2: # %normal1 +; RV32I-NEXT: li a0, 0 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB12_3: # Block address taken +; RV32I-NEXT: # %fail +; RV32I-NEXT: # Label of block must be emitted +; RV32I-NEXT: li a0, 1 +; RV32I-NEXT: ret +; +; RV64I-LABEL: constraint_m_with_multi_callbr_asm: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: lui a1, %hi(eg) +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a1); beqz a0, .LBB12_3 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: # %bb.1: # %normal0 +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a1); beqz a0, .LBB12_3 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: # %bb.2: # %normal1 +; RV64I-NEXT: li a0, 0 +; RV64I-NEXT: ret +; RV64I-NEXT: .LBB12_3: # Block address taken +; RV64I-NEXT: # %fail +; RV64I-NEXT: # Label of block must be emitted +; RV64I-NEXT: li a0, 1 +; RV64I-NEXT: ret +; +; RV32I-MEDIUM-LABEL: constraint_m_with_multi_callbr_asm: +; RV32I-MEDIUM: # %bb.0: # %entry +; RV32I-MEDIUM-NEXT: .Lpcrel_hi9: +; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg) +; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi9) +; RV32I-MEDIUM-NEXT: #APP +; RV32I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB12_3 +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: # %bb.1: # %normal0 +; RV32I-MEDIUM-NEXT: #APP +; RV32I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB12_3 +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: # %bb.2: # %normal1 +; RV32I-MEDIUM-NEXT: li a0, 0 +; RV32I-MEDIUM-NEXT: ret +; RV32I-MEDIUM-NEXT: .LBB12_3: # Block address taken +; RV32I-MEDIUM-NEXT: # %fail +; RV32I-MEDIUM-NEXT: # Label of block must be emitted +; RV32I-MEDIUM-NEXT: li a0, 1 +; RV32I-MEDIUM-NEXT: ret +; +; RV64I-MEDIUM-LABEL: constraint_m_with_multi_callbr_asm: +; RV64I-MEDIUM: # %bb.0: # %entry +; RV64I-MEDIUM-NEXT: .Lpcrel_hi9: +; RV64I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg) +; RV64I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi9) +; RV64I-MEDIUM-NEXT: #APP +; RV64I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB12_3 +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: # %bb.1: # %normal0 +; RV64I-MEDIUM-NEXT: #APP +; RV64I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB12_3 +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: # %bb.2: # %normal1 +; RV64I-MEDIUM-NEXT: li a0, 0 +; RV64I-MEDIUM-NEXT: ret +; RV64I-MEDIUM-NEXT: .LBB12_3: # Block address taken +; RV64I-MEDIUM-NEXT: # %fail +; RV64I-MEDIUM-NEXT: # Label of block must be emitted +; RV64I-MEDIUM-NEXT: li a0, 1 +; RV64I-MEDIUM-NEXT: ret +entry: + callbr void asm "sw zero, $0; beqz $1, $2", "=*m,r,!i"(ptr elementtype(i32) @eg, i32 %a) to label %normal0 [label %fail] + +normal0: + callbr void asm "sw zero, $0; beqz $1, $2", "=*m,r,!i"(ptr elementtype(i32) @eg, i32 %a) to label %normal1 [label %fail] + +normal1: + ret i32 0 + +fail: + ret i32 1 +} + define void @constraint_o_1(ptr %a) nounwind { ; RV32I-LABEL: constraint_o_1: ; RV32I: # %bb.0: @@ -470,9 +730,9 @@ ; ; RV32I-MEDIUM-LABEL: constraint_o_with_global_1: ; RV32I-MEDIUM: # %bb.0: -; RV32I-MEDIUM-NEXT: .Lpcrel_hi6: +; RV32I-MEDIUM-NEXT: .Lpcrel_hi10: ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi6) +; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi10) ; RV32I-MEDIUM-NEXT: #APP ; RV32I-MEDIUM-NEXT: sw zero, 0(a0) ; RV32I-MEDIUM-NEXT: #NO_APP @@ -480,9 +740,9 @@ ; ; RV64I-MEDIUM-LABEL: constraint_o_with_global_1: ; RV64I-MEDIUM: # %bb.0: -; RV64I-MEDIUM-NEXT: .Lpcrel_hi6: +; RV64I-MEDIUM-NEXT: .Lpcrel_hi10: ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi6) +; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi10) ; RV64I-MEDIUM-NEXT: #APP ; RV64I-MEDIUM-NEXT: sw zero, 0(a0) ; RV64I-MEDIUM-NEXT: #NO_APP @@ -512,9 +772,9 @@ ; ; RV32I-MEDIUM-LABEL: constraint_o_with_global_2: ; RV32I-MEDIUM: # %bb.0: -; RV32I-MEDIUM-NEXT: .Lpcrel_hi7: +; RV32I-MEDIUM-NEXT: .Lpcrel_hi11: ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi7) +; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi11) ; RV32I-MEDIUM-NEXT: #APP ; RV32I-MEDIUM-NEXT: sw zero, 4(a0) ; RV32I-MEDIUM-NEXT: #NO_APP @@ -522,9 +782,9 @@ ; ; RV64I-MEDIUM-LABEL: constraint_o_with_global_2: ; RV64I-MEDIUM: # %bb.0: -; RV64I-MEDIUM-NEXT: .Lpcrel_hi7: +; RV64I-MEDIUM-NEXT: .Lpcrel_hi11: ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) -; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi7) +; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi11) ; RV64I-MEDIUM-NEXT: #APP ; RV64I-MEDIUM-NEXT: sw zero, 4(a0) ; RV64I-MEDIUM-NEXT: #NO_APP @@ -554,9 +814,9 @@ ; ; RV32I-MEDIUM-LABEL: constraint_o_with_global_3: ; RV32I-MEDIUM: # %bb.0: -; RV32I-MEDIUM-NEXT: .Lpcrel_hi8: +; RV32I-MEDIUM-NEXT: .Lpcrel_hi12: ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg+8000) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi8) +; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi12) ; RV32I-MEDIUM-NEXT: #APP ; RV32I-MEDIUM-NEXT: sw zero, 0(a0) ; RV32I-MEDIUM-NEXT: #NO_APP @@ -564,9 +824,9 @@ ; ; RV64I-MEDIUM-LABEL: constraint_o_with_global_3: ; RV64I-MEDIUM: # %bb.0: -; RV64I-MEDIUM-NEXT: .Lpcrel_hi8: +; RV64I-MEDIUM-NEXT: .Lpcrel_hi12: ; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg+8000) -; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi8) +; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi12) ; RV64I-MEDIUM-NEXT: #APP ; RV64I-MEDIUM-NEXT: sw zero, 0(a0) ; RV64I-MEDIUM-NEXT: #NO_APP @@ -594,9 +854,9 @@ ; ; RV32I-MEDIUM-LABEL: constraint_o_with_extern_weak_global_1: ; RV32I-MEDIUM: # %bb.0: -; RV32I-MEDIUM-NEXT: .Lpcrel_hi9: +; RV32I-MEDIUM-NEXT: .Lpcrel_hi13: ; RV32I-MEDIUM-NEXT: auipc a0, %got_pcrel_hi(ewg) -; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi9)(a0) +; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi13)(a0) ; RV32I-MEDIUM-NEXT: #APP ; RV32I-MEDIUM-NEXT: sw zero, 0(a0) ; RV32I-MEDIUM-NEXT: #NO_APP @@ -604,9 +864,9 @@ ; ; RV64I-MEDIUM-LABEL: constraint_o_with_extern_weak_global_1: ; RV64I-MEDIUM: # %bb.0: -; RV64I-MEDIUM-NEXT: .Lpcrel_hi9: +; RV64I-MEDIUM-NEXT: .Lpcrel_hi13: ; RV64I-MEDIUM-NEXT: auipc a0, %got_pcrel_hi(ewg) -; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi9)(a0) +; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi13)(a0) ; RV64I-MEDIUM-NEXT: #APP ; RV64I-MEDIUM-NEXT: sw zero, 0(a0) ; RV64I-MEDIUM-NEXT: #NO_APP @@ -636,9 +896,9 @@ ; ; RV32I-MEDIUM-LABEL: constraint_o_with_extern_weak_global_2: ; RV32I-MEDIUM: # %bb.0: -; RV32I-MEDIUM-NEXT: .Lpcrel_hi10: +; RV32I-MEDIUM-NEXT: .Lpcrel_hi14: ; RV32I-MEDIUM-NEXT: auipc a0, %got_pcrel_hi(ewg) -; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi10)(a0) +; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi14)(a0) ; RV32I-MEDIUM-NEXT: #APP ; RV32I-MEDIUM-NEXT: sw zero, 4(a0) ; RV32I-MEDIUM-NEXT: #NO_APP @@ -646,9 +906,9 @@ ; ; RV64I-MEDIUM-LABEL: constraint_o_with_extern_weak_global_2: ; RV64I-MEDIUM: # %bb.0: -; RV64I-MEDIUM-NEXT: .Lpcrel_hi10: +; RV64I-MEDIUM-NEXT: .Lpcrel_hi14: ; RV64I-MEDIUM-NEXT: auipc a0, %got_pcrel_hi(ewg) -; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi10)(a0) +; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi14)(a0) ; RV64I-MEDIUM-NEXT: #APP ; RV64I-MEDIUM-NEXT: sw zero, 4(a0) ; RV64I-MEDIUM-NEXT: #NO_APP @@ -678,9 +938,9 @@ ; ; RV32I-MEDIUM-LABEL: constraint_o_with_extern_weak_global_3: ; RV32I-MEDIUM: # %bb.0: -; RV32I-MEDIUM-NEXT: .Lpcrel_hi11: +; RV32I-MEDIUM-NEXT: .Lpcrel_hi15: ; RV32I-MEDIUM-NEXT: auipc a0, %got_pcrel_hi(ewg) -; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi11)(a0) +; RV32I-MEDIUM-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi15)(a0) ; RV32I-MEDIUM-NEXT: lui a1, 2 ; RV32I-MEDIUM-NEXT: addi a1, a1, -192 ; RV32I-MEDIUM-NEXT: add a0, a0, a1 @@ -691,9 +951,9 @@ ; ; RV64I-MEDIUM-LABEL: constraint_o_with_extern_weak_global_3: ; RV64I-MEDIUM: # %bb.0: -; RV64I-MEDIUM-NEXT: .Lpcrel_hi11: +; RV64I-MEDIUM-NEXT: .Lpcrel_hi15: ; RV64I-MEDIUM-NEXT: auipc a0, %got_pcrel_hi(ewg) -; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi11)(a0) +; RV64I-MEDIUM-NEXT: ld a0, %pcrel_lo(.Lpcrel_hi15)(a0) ; RV64I-MEDIUM-NEXT: lui a1, 2 ; RV64I-MEDIUM-NEXT: addiw a1, a1, -192 ; RV64I-MEDIUM-NEXT: add a0, a0, a1 @@ -705,6 +965,266 @@ ret void } +define void @constraint_o_with_multi_operands() nounwind { +; RV32I-LABEL: constraint_o_with_multi_operands: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a0, %hi(eg) +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a0) \n sw zero, %lo(eg)(a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: constraint_o_with_multi_operands: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a0, %hi(eg) +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a0) \n sw zero, %lo(eg)(a0) +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret +; +; RV32I-MEDIUM-LABEL: constraint_o_with_multi_operands: +; RV32I-MEDIUM: # %bb.0: +; RV32I-MEDIUM-NEXT: .Lpcrel_hi16: +; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) +; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi16) +; RV32I-MEDIUM-NEXT: #APP +; RV32I-MEDIUM-NEXT: sw zero, 0(a0) \n sw zero, 0(a0) +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: ret +; +; RV64I-MEDIUM-LABEL: constraint_o_with_multi_operands: +; RV64I-MEDIUM: # %bb.0: +; RV64I-MEDIUM-NEXT: .Lpcrel_hi16: +; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) +; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi16) +; RV64I-MEDIUM-NEXT: #APP +; RV64I-MEDIUM-NEXT: sw zero, 0(a0) \n sw zero, 0(a0) +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: ret + call void asm "sw zero, $0 \n sw zero, $1", "=*o,=*o"(ptr elementtype(i32) @eg, ptr elementtype(i32) @eg) + ret void +} + +define void @constraint_o_with_multi_asm() nounwind { +; RV32I-LABEL: constraint_o_with_multi_asm: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a0, %hi(eg) +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: constraint_o_with_multi_asm: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a0, %hi(eg) +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a0) +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a0) +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret +; +; RV32I-MEDIUM-LABEL: constraint_o_with_multi_asm: +; RV32I-MEDIUM: # %bb.0: +; RV32I-MEDIUM-NEXT: .Lpcrel_hi17: +; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) +; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi17) +; RV32I-MEDIUM-NEXT: #APP +; RV32I-MEDIUM-NEXT: sw zero, 0(a0) +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: #APP +; RV32I-MEDIUM-NEXT: sw zero, 0(a0) +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: ret +; +; RV64I-MEDIUM-LABEL: constraint_o_with_multi_asm: +; RV64I-MEDIUM: # %bb.0: +; RV64I-MEDIUM-NEXT: .Lpcrel_hi17: +; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg) +; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi17) +; RV64I-MEDIUM-NEXT: #APP +; RV64I-MEDIUM-NEXT: sw zero, 0(a0) +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: #APP +; RV64I-MEDIUM-NEXT: sw zero, 0(a0) +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: ret + call void asm "sw zero, $0", "=*o"(ptr elementtype(i32) @eg) + call void asm "sw zero, $0", "=*o"(ptr elementtype(i32) @eg) + ret void +} + +define i32 @constraint_o_with_callbr_multi_operands(i32 %a) { +; RV32I-LABEL: constraint_o_with_callbr_multi_operands: +; RV32I: # %bb.0: # %entry +; RV32I-NEXT: lui a1, %hi(eg) +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a1); sw zero, %lo(eg)(a1); beqz a0, .LBB24_2 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: # %bb.1: # %normal +; RV32I-NEXT: li a0, 0 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB24_2: # Block address taken +; RV32I-NEXT: # %fail +; RV32I-NEXT: # Label of block must be emitted +; RV32I-NEXT: li a0, 1 +; RV32I-NEXT: ret +; +; RV64I-LABEL: constraint_o_with_callbr_multi_operands: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: lui a1, %hi(eg) +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a1); sw zero, %lo(eg)(a1); beqz a0, .LBB24_2 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: # %bb.1: # %normal +; RV64I-NEXT: li a0, 0 +; RV64I-NEXT: ret +; RV64I-NEXT: .LBB24_2: # Block address taken +; RV64I-NEXT: # %fail +; RV64I-NEXT: # Label of block must be emitted +; RV64I-NEXT: li a0, 1 +; RV64I-NEXT: ret +; +; RV32I-MEDIUM-LABEL: constraint_o_with_callbr_multi_operands: +; RV32I-MEDIUM: # %bb.0: # %entry +; RV32I-MEDIUM-NEXT: .Lpcrel_hi18: +; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg) +; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi18) +; RV32I-MEDIUM-NEXT: #APP +; RV32I-MEDIUM-NEXT: sw zero, 0(a1); sw zero, 0(a1); beqz a0, .LBB24_2 +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: # %bb.1: # %normal +; RV32I-MEDIUM-NEXT: li a0, 0 +; RV32I-MEDIUM-NEXT: ret +; RV32I-MEDIUM-NEXT: .LBB24_2: # Block address taken +; RV32I-MEDIUM-NEXT: # %fail +; RV32I-MEDIUM-NEXT: # Label of block must be emitted +; RV32I-MEDIUM-NEXT: li a0, 1 +; RV32I-MEDIUM-NEXT: ret +; +; RV64I-MEDIUM-LABEL: constraint_o_with_callbr_multi_operands: +; RV64I-MEDIUM: # %bb.0: # %entry +; RV64I-MEDIUM-NEXT: .Lpcrel_hi18: +; RV64I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg) +; RV64I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi18) +; RV64I-MEDIUM-NEXT: #APP +; RV64I-MEDIUM-NEXT: sw zero, 0(a1); sw zero, 0(a1); beqz a0, .LBB24_2 +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: # %bb.1: # %normal +; RV64I-MEDIUM-NEXT: li a0, 0 +; RV64I-MEDIUM-NEXT: ret +; RV64I-MEDIUM-NEXT: .LBB24_2: # Block address taken +; RV64I-MEDIUM-NEXT: # %fail +; RV64I-MEDIUM-NEXT: # Label of block must be emitted +; RV64I-MEDIUM-NEXT: li a0, 1 +; RV64I-MEDIUM-NEXT: ret +entry: + callbr void asm "sw zero, $0; sw zero, $1; beqz $2, $3", "=*m,=*m,r,!i"(ptr elementtype(i32) @eg, ptr elementtype(i32) @eg, i32 %a) to label %normal [label %fail] + +normal: + ret i32 0 + +fail: + ret i32 1 +} + +define i32 @constraint_o_with_multi_callbr_asm(i32 %a) { +; RV32I-LABEL: constraint_o_with_multi_callbr_asm: +; RV32I: # %bb.0: # %entry +; RV32I-NEXT: lui a1, %hi(eg) +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a1); beqz a0, .LBB25_3 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: # %bb.1: # %normal0 +; RV32I-NEXT: #APP +; RV32I-NEXT: sw zero, %lo(eg)(a1); beqz a0, .LBB25_3 +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: # %bb.2: # %normal1 +; RV32I-NEXT: li a0, 0 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB25_3: # Block address taken +; RV32I-NEXT: # %fail +; RV32I-NEXT: # Label of block must be emitted +; RV32I-NEXT: li a0, 1 +; RV32I-NEXT: ret +; +; RV64I-LABEL: constraint_o_with_multi_callbr_asm: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: lui a1, %hi(eg) +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a1); beqz a0, .LBB25_3 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: # %bb.1: # %normal0 +; RV64I-NEXT: #APP +; RV64I-NEXT: sw zero, %lo(eg)(a1); beqz a0, .LBB25_3 +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: # %bb.2: # %normal1 +; RV64I-NEXT: li a0, 0 +; RV64I-NEXT: ret +; RV64I-NEXT: .LBB25_3: # Block address taken +; RV64I-NEXT: # %fail +; RV64I-NEXT: # Label of block must be emitted +; RV64I-NEXT: li a0, 1 +; RV64I-NEXT: ret +; +; RV32I-MEDIUM-LABEL: constraint_o_with_multi_callbr_asm: +; RV32I-MEDIUM: # %bb.0: # %entry +; RV32I-MEDIUM-NEXT: .Lpcrel_hi19: +; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg) +; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi19) +; RV32I-MEDIUM-NEXT: #APP +; RV32I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB25_3 +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: # %bb.1: # %normal0 +; RV32I-MEDIUM-NEXT: #APP +; RV32I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB25_3 +; RV32I-MEDIUM-NEXT: #NO_APP +; RV32I-MEDIUM-NEXT: # %bb.2: # %normal1 +; RV32I-MEDIUM-NEXT: li a0, 0 +; RV32I-MEDIUM-NEXT: ret +; RV32I-MEDIUM-NEXT: .LBB25_3: # Block address taken +; RV32I-MEDIUM-NEXT: # %fail +; RV32I-MEDIUM-NEXT: # Label of block must be emitted +; RV32I-MEDIUM-NEXT: li a0, 1 +; RV32I-MEDIUM-NEXT: ret +; +; RV64I-MEDIUM-LABEL: constraint_o_with_multi_callbr_asm: +; RV64I-MEDIUM: # %bb.0: # %entry +; RV64I-MEDIUM-NEXT: .Lpcrel_hi19: +; RV64I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg) +; RV64I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi19) +; RV64I-MEDIUM-NEXT: #APP +; RV64I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB25_3 +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: # %bb.1: # %normal0 +; RV64I-MEDIUM-NEXT: #APP +; RV64I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB25_3 +; RV64I-MEDIUM-NEXT: #NO_APP +; RV64I-MEDIUM-NEXT: # %bb.2: # %normal1 +; RV64I-MEDIUM-NEXT: li a0, 0 +; RV64I-MEDIUM-NEXT: ret +; RV64I-MEDIUM-NEXT: .LBB25_3: # Block address taken +; RV64I-MEDIUM-NEXT: # %fail +; RV64I-MEDIUM-NEXT: # Label of block must be emitted +; RV64I-MEDIUM-NEXT: li a0, 1 +; RV64I-MEDIUM-NEXT: ret +entry: + callbr void asm "sw zero, $0; beqz $1, $2", "=*o,r,!i"(ptr elementtype(i32) @eg, i32 %a) to label %normal0 [label %fail] + +normal0: + callbr void asm "sw zero, $0; beqz $1, $2", "=*o,r,!i"(ptr elementtype(i32) @eg, i32 %a) to label %normal1 [label %fail] + +normal1: + ret i32 0 + +fail: + ret i32 1 +} + define void @constraint_A(ptr %a) nounwind { ; RV32I-LABEL: constraint_A: ; RV32I: # %bb.0: