648 changes: 562 additions & 86 deletions llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,17 @@ define void @constraint_m_with_global_1() nounwind {
; 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
;
; RV64I-MEDIUM-LABEL: constraint_m_with_global_1:
; 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)
Expand All @@ -147,39 +145,35 @@ define void @constraint_m_with_global_1() nounwind {
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))
Expand All @@ -190,38 +184,34 @@ define void @constraint_m_with_global_3() nounwind {
; 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
;
; RV32I-MEDIUM-LABEL: constraint_m_with_global_3:
; 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
;
; RV64I-MEDIUM-LABEL: constraint_m_with_global_3:
; 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))
Expand Down Expand Up @@ -271,19 +261,17 @@ define void @constraint_m_with_extern_weak_global_1() nounwind {
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
;
Expand Down Expand Up @@ -314,18 +302,16 @@ define void @constraint_m_with_extern_weak_global_3() nounwind {
; 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
;
Expand Down Expand Up @@ -358,6 +344,258 @@ define void @constraint_m_with_extern_weak_global_3() nounwind {
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: #APP
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi6)(a0); sw zero, %pcrel_lo(.Lpcrel_hi6)(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: #APP
; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi6)(a0); sw zero, %pcrel_lo(.Lpcrel_hi6)(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: #APP
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi7)(a0)
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: #APP
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi7)(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: #APP
; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi7)(a0)
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: #APP
; 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", "=*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: #APP
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi8)(a1); sw zero, %pcrel_lo(.Lpcrel_hi8)(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: #APP
; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi8)(a1); sw zero, %pcrel_lo(.Lpcrel_hi8)(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: #APP
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi9)(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, %pcrel_lo(.Lpcrel_hi9)(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: #APP
; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi9)(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, %pcrel_lo(.Lpcrel_hi9)(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:
Expand Down Expand Up @@ -470,21 +708,19 @@ define void @constraint_o_with_global_1() nounwind {
;
; 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: #APP
; RV32I-MEDIUM-NEXT: sw zero, 0(a0)
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi10)(a0)
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: ret
;
; 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: #APP
; RV64I-MEDIUM-NEXT: sw zero, 0(a0)
; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi10)(a0)
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: ret
call void asm "sw zero, $0", "=*o"(ptr elementtype(i32) @eg)
Expand All @@ -494,39 +730,35 @@ define void @constraint_o_with_global_1() nounwind {
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: .Lpcrel_hi11:
; 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_hi11)(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: .Lpcrel_hi11:
; 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_hi11)(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))
Expand All @@ -537,38 +769,34 @@ define void @constraint_o_with_global_3() nounwind {
; 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
;
; 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: #APP
; RV32I-MEDIUM-NEXT: sw zero, 0(a0)
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi12)(a0)
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: ret
;
; 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: #APP
; RV64I-MEDIUM-NEXT: sw zero, 0(a0)
; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi12)(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))
Expand All @@ -594,19 +822,19 @@ define void @constraint_o_with_extern_weak_global_1() nounwind {
;
; 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
; RV32I-MEDIUM-NEXT: ret
;
; 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
Expand All @@ -618,37 +846,35 @@ define void @constraint_o_with_extern_weak_global_1() nounwind {
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
;
; 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
; RV32I-MEDIUM-NEXT: ret
;
; 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
Expand All @@ -661,26 +887,24 @@ define void @constraint_o_with_extern_weak_global_3() nounwind {
; 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
;
; 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
Expand All @@ -691,9 +915,9 @@ define void @constraint_o_with_extern_weak_global_3() nounwind {
;
; 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
Expand All @@ -705,6 +929,258 @@ define void @constraint_o_with_extern_weak_global_3() nounwind {
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: #APP
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi16)(a0) \n sw zero, %pcrel_lo(.Lpcrel_hi16)(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: #APP
; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi16)(a0) \n sw zero, %pcrel_lo(.Lpcrel_hi16)(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: #APP
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi17)(a0)
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: #APP
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi17)(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: #APP
; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi17)(a0)
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: #APP
; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi17)(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: #APP
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi18)(a1); sw zero, %pcrel_lo(.Lpcrel_hi18)(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: #APP
; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi18)(a1); sw zero, %pcrel_lo(.Lpcrel_hi18)(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: #APP
; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi19)(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, %pcrel_lo(.Lpcrel_hi19)(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: #APP
; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi19)(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, %pcrel_lo(.Lpcrel_hi19)(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:
Expand Down