; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py ; RUN: llc -mtriple=riscv32 -O0 -global-isel -stop-after=irtranslator -o - %s | FileCheck %s define void @test_simple_memory_clobber() { ; CHECK-LABEL: name: test_simple_memory_clobber ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect mayload maystore attdialect ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "~{memory}"() call void asm sideeffect "", ""() ret void } define void @test_simple_register_clobber() { ; CHECK-LABEL: name: test_simple_register_clobber ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, clobber, implicit-def early-clobber $x10 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "~{x10}"() ret void } define i32 @test_single_register_output() nounwind { ; CHECK-LABEL: name: test_single_register_output ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", attdialect, regdef:GPRNoX0, def %0 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY %0 ; CHECK-NEXT: $x10 = COPY [[COPY]](s32) ; CHECK-NEXT: PseudoRET implicit $x10 %1 = tail call i32 asm "", "=r"() nounwind ret i32 %1 } define i32 @test_multiple_registers_output() nounwind { ; CHECK-LABEL: name: test_multiple_registers_output ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", attdialect, regdef:GPRNoX0, def %0, regdef:GPRNoX0, def %1 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY %0 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY1]] ; CHECK-NEXT: $x10 = COPY [[ADD]](s32) ; CHECK-NEXT: PseudoRET implicit $x10 %1 = tail call { i32, i32 } asm "", "=r,=r"() nounwind %asmresult = extractvalue { i32, i32 } %1, 0 %asmresult1 = extractvalue { i32, i32 } %1, 1 %add = add i32 %asmresult, %asmresult1 ret i32 %add } define i32 @test_specific_register_output_trunc() nounwind { ; CHECK-LABEL: name: test_specific_register_output_trunc ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"mov ${0:w}, 7", attdialect, regdef, implicit-def $x10 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 ; CHECK-NEXT: $x10 = COPY [[COPY]](s32) ; CHECK-NEXT: PseudoRET implicit $x10 %1 = tail call i32 asm "mov ${0:w}, 7", "={x10}"() nounwind ret i32 %1 } define zeroext i8 @test_register_output_trunc(ptr %src) nounwind { ; CHECK-LABEL: name: test_register_output_trunc ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: liveins: $x10 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 ; CHECK-NEXT: INLINEASM &"mov ${0:w}, 32", attdialect, regdef:GPRNoX0, def %1 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) ; CHECK-NEXT: $x10 = COPY [[ZEXT]](s32) ; CHECK-NEXT: PseudoRET implicit $x10 %1 = tail call i8 asm "mov ${0:w}, 32", "=r"() nounwind ret i8 %1 } define i32 @asm_multiple_registers_early_clobber() nounwind { ; CHECK-LABEL: name: asm_multiple_registers_early_clobber ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", attdialect, regdef-ec:GPRNoX0, def early-clobber %0, regdef-ec:GPRNoX0, def early-clobber %1 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY %0 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY1]] ; CHECK-NEXT: $x10 = COPY [[ADD]](s32) ; CHECK-NEXT: PseudoRET implicit $x10 %1 = tail call { i32, i32 } asm "", "=&r,=&r"() nounwind %asmresult = extractvalue { i32, i32 } %1, 0 %asmresult1 = extractvalue { i32, i32 } %1, 1 %add = add i32 %asmresult, %asmresult1 ret i32 %add } define void @test_input_register_pointer(ptr %p) { ; CHECK-LABEL: name: test_input_register_pointer ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: liveins: $x10 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gprnox0 = COPY [[COPY]](p0) ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, reguse:GPRNoX0, [[COPY1]] ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "r"(ptr %p) ret void } define void @test_input_register_imm() { ; CHECK-LABEL: name: test_input_register_imm ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gprnox0 = COPY [[C]](s32) ; CHECK-NEXT: INLINEASM &"mov x0, $0", sideeffect attdialect, reguse:GPRNoX0, [[COPY]] ; CHECK-NEXT: PseudoRET call void asm sideeffect "mov x0, $0", "r"(i32 42) ret void } define i32 @test_boolean_imm_ext() { ; CHECK-LABEL: name: test_boolean_imm_ext ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; CHECK-NEXT: INLINEASM &"#TEST 42 + ${0:c} - .\0A\09", sideeffect mayload attdialect, imm, 1 ; CHECK-NEXT: $x10 = COPY [[C]](s32) ; CHECK-NEXT: PseudoRET implicit $x10 tail call void asm sideeffect "#TEST 42 + ${0:c} - .\0A\09", "i"(i1 true) ret i32 1 } define void @test_input_imm() { ; CHECK-LABEL: name: test_input_imm ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect mayload attdialect, imm, 42 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "i"(i32 42) ret void } @var = global i64 0, align 8 define void @test_immediate_constraint_sym() { ; CHECK-LABEL: name: test_immediate_constraint_sym ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect mayload attdialect, imm, @var ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "i"(ptr @var) ret void } define void @test_s_constraint() { ; CHECK-LABEL: name: test_s_constraint ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect mayload attdialect, imm, @var ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "s"(ptr @var) ret void } define zeroext i8 @test_input_register(ptr %src) nounwind { ; CHECK-LABEL: name: test_input_register ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: liveins: $x10 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gprnox0 = COPY [[COPY]](p0) ; CHECK-NEXT: INLINEASM &"", attdialect, regdef:GPRNoX0, def %1, reguse:GPRNoX0, [[COPY1]] ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY %1 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY2]](s32) ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) ; CHECK-NEXT: $x10 = COPY [[ZEXT]](s32) ; CHECK-NEXT: PseudoRET implicit $x10 %1 = tail call i8 asm "", "=r,r"(ptr %src) nounwind ret i8 %1 } define i32 @test_memory_constraint(ptr %a) nounwind { ; CHECK-LABEL: name: test_memory_constraint ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: liveins: $x10 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 ; CHECK-NEXT: INLINEASM &"ldr $0, $1", mayload attdialect, regdef:GPRNoX0, def %1, mem:m, [[COPY]](p0) ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 ; CHECK-NEXT: $x10 = COPY [[COPY1]](s32) ; CHECK-NEXT: PseudoRET implicit $x10 %1 = tail call i32 asm "ldr $0, $1", "=r,*m"(ptr elementtype(i32) %a) ret i32 %1 } define i16 @test_anyext_input() { ; CHECK-LABEL: name: test_anyext_input ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16) ; CHECK-NEXT: [[COPY:%[0-9]+]]:gprnox0 = COPY [[ANYEXT]](s32) ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, regdef:GPRNoX0, def %0, reguse:GPRNoX0, [[COPY]] ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %0 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) ; CHECK-NEXT: $x10 = COPY [[ANYEXT1]](s32) ; CHECK-NEXT: PseudoRET implicit $x10 %1 = call i16 asm sideeffect "", "=r,r"(i16 1) ret i16 %1 } define i16 @test_anyext_input_with_matching_constraint() { ; CHECK-LABEL: name: test_anyext_input_with_matching_constraint ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16) ; CHECK-NEXT: [[COPY:%[0-9]+]]:gprnox0 = COPY [[ANYEXT]](s32) ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, regdef:GPRNoX0, def %0, reguse tiedto:$0, [[COPY]](tied-def 3) ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %0 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) ; CHECK-NEXT: $x10 = COPY [[ANYEXT1]](s32) ; CHECK-NEXT: PseudoRET implicit $x10 %1 = call i16 asm sideeffect "", "=r,0"(i16 1) ret i16 %1 } define float @test_multiple_register_outputs_same() #0 { ; CHECK-LABEL: name: test_multiple_register_outputs_same ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"mov $0, #0; mov $1, #0", attdialect, regdef:GPRNoX0, def %0, regdef:GPRNoX0, def %1 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY %0 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 ; CHECK-NEXT: [[FADD:%[0-9]+]]:_(s32) = G_FADD [[COPY]], [[COPY1]] ; CHECK-NEXT: $x10 = COPY [[FADD]](s32) ; CHECK-NEXT: PseudoRET implicit $x10 %1 = call { float, float } asm "mov $0, #0; mov $1, #0", "=r,=r"() %asmresult = extractvalue { float, float } %1, 0 %asmresult1 = extractvalue { float, float } %1, 1 %add = fadd float %asmresult, %asmresult1 ret float %add } ; RISC-V Specific constraints define void @test_input_imm_K() { ; CHECK-LABEL: name: test_input_imm_K ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, 21 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "K"(i32 21) ret void } define void @test_input_imm_K_boundary_value_31() { ; CHECK-LABEL: name: test_input_imm_K_boundary_value_31 ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, 31 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "K"(i32 31) ret void } define void @test_input_imm_K_boundary_value_0() { ; CHECK-LABEL: name: test_input_imm_K_boundary_value_0 ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, 0 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "K"(i32 0) ret void } define void @test_input_imm_K_i2() { ; CHECK-LABEL: name: test_input_imm_K_i2 ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, 3 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "K"(i2 3) ret void } define void @test_input_imm_K_i1_0() { ; CHECK-LABEL: name: test_input_imm_K_i1_0 ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, 0 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "K"(i1 0) ret void } define void @test_input_imm_K_i1_1() { ; CHECK-LABEL: name: test_input_imm_K_i1_1 ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, 0 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "K"(i1 0) ret void } define void @test_input_imm_I() { ; CHECK-LABEL: name: test_input_imm_I ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, 42 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "I"(i32 42) ret void } define void @test_input_imm_I_boundary_value_2047() { ; CHECK-LABEL: name: test_input_imm_I_boundary_value_2047 ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, 2047 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "I"(i32 2047) ret void } define void @test_input_imm_I_boundary_value_minus_2048() { ; CHECK-LABEL: name: test_input_imm_I_boundary_value_minus_2048 ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, -2048 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "I"(i32 -2048) ret void } define void @test_input_imm_I_i2() { ; CHECK-LABEL: name: test_input_imm_I_i2 ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, -1 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "I"(i2 3) ret void } define void @test_input_imm_I_i1_0() { ; CHECK-LABEL: name: test_input_imm_I_i1_0 ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, 0 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "K"(i1 0) ret void } define void @test_input_imm_I_i1_1() { ; CHECK-LABEL: name: test_input_imm_I_i1_1 ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, 1 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "K"(i1 1) ret void } define void @test_S_constraint() { ; CHECK-LABEL: name: test_S_constraint ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect mayload attdialect, imm, @var ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "S"(ptr @var) ret void } define void @test_J_constraint() { ; CHECK-LABEL: name: test_J_constraint ; CHECK: bb.1 (%ir-block.0): ; CHECK-NEXT: INLINEASM &"", sideeffect attdialect, imm, 0 ; CHECK-NEXT: PseudoRET call void asm sideeffect "", "J"(i8 0) ret void }