| //@ only-x86_64 |
| //@ compile-flags: -C no-prepopulate-passes |
| #![feature(asm_goto_with_outputs)] |
| #![crate_type = "lib"] |
| use std::arch::asm; |
| |
| // Regression test for #137867. Check that critical edges have been split before code generation, |
| // and so all stores to the asm output occur on disjoint paths without any of them jumping to |
| // another callbr label. |
| // |
| // CHECK-LABEL: @f( |
| // CHECK: [[OUT:%.*]] = callbr i32 asm |
| // CHECK-NEXT: to label %[[BB0:.*]] [label %[[BB1:.*]], label %[[BB2:.*]]], |
| // CHECK: [[BB1]]: |
| // CHECK-NEXT: store i32 [[OUT]], ptr %a |
| // CHECK-NEXT: br label %[[BBR:.*]] |
| // CHECK: [[BB2]]: |
| // CHECK-NEXT: store i32 [[OUT]], ptr %a |
| // CHECK-NEXT: br label %[[BBR]] |
| // CHECK: [[BB0]]: |
| // CHECK-NEXT: store i32 [[OUT]], ptr %a |
| // CHECK-NEXT: br label %[[BBR]] |
| // CHECK: [[BBR]]: |
| // CHECK-NEXT: [[RET:%.*]] = load i32, ptr %a |
| // CHECK-NEXT: ret i32 [[RET]] |
| #[unsafe(no_mangle)] |
| pub unsafe fn f(mut a: u32) -> u32 { |
| asm!( |
| "jmp {} |
| jmp {}", |
| label {}, |
| label {}, |
| inout("eax") a, |
| ); |
| a |
| } |