"which mangling version to use for symbol names"),
binary_dep_depinfo: bool = (false, parse_bool, [TRACKED],
"include artifacts (sysroot, crate dependencies) used during compilation in dep-info"),
+ insert_sideeffect: bool = (false, parse_bool, [TRACKED],
+ "fix undefined behavior when a thread doesn't eventually make progress \
+ (such as entering an empty infinite loop) by inserting llvm.sideeffect"),
}
pub fn default_lib_output() -> CrateType {
}
fn sideeffect(&mut self) {
- let fnname = self.get_intrinsic(&("llvm.sideeffect"));
- self.call(fnname, &[], None);
+ if self.tcx.sess.opts.debugging_opts.insert_sideeffect {
+ let fnname = self.get_intrinsic(&("llvm.sideeffect"));
+ self.call(fnname, &[], None);
+ }
}
fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value {
bx: &mut Bx,
targets: &[mir::BasicBlock],
) {
- if targets.iter().any(|target| {
- *target <= *self.bb
- && target
- .start_location()
- .is_predecessor_of(self.bb.start_location(), mir)
- }) {
- bx.sideeffect();
+ if bx.tcx().sess.opts.debugging_opts.insert_sideeffect {
+ if targets.iter().any(|target| {
+ *target <= *self.bb
+ && target
+ .start_location()
+ .is_predecessor_of(self.bb.start_location(), mir)
+ }) {
+ bx.sideeffect();
+ }
}
}
}
pub fn alloc_test(data: u32) {
// CHECK-LABEL: @alloc_test
// CHECK-NEXT: start:
- // CHECK-NOT: alloc
- // CHECK: ret void
+ // CHECK-NEXT: ret void
let x = Box::new(data);
drop(x);
}
pub fn a(a: Box<i32>) {
// CHECK-LABEL: define void @a
// CHECK: call void @__rust_dealloc
- // CHECK: call void @foo
+ // CHECK-NEXT: call void @foo
let _a = A;
drop(a);
}
#[no_mangle]
pub fn issue_34947(x: i32) -> i32 {
// CHECK: mul
- // CHECK-NOT: br label
- // CHECK: mul
- // CHECK-NOT: br label
- // CHECK: mul
- // CHECK-NOT: br label
- // CHECK: ret
+ // CHECK-NEXT: mul
+ // CHECK-NEXT: mul
+ // CHECK-NEXT: ret
x.pow(5)
}
-// ignore-test
-
-// FIXME:
-// LLVM can't optimize some loops with a large number of iterations because of
-// @llvm.sideeffect() (see also #59546)
-
// compile-flags: -O
// ignore-debug: the debug assertions get in the way
+// ignore-tidy-linelength
+
// compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]
#[naked]
pub fn naked_recursive() {
// CHECK-NEXT: {{.+}}:
- // CHECK: call void @naked_empty()
+ // CHECK-NEXT: call void @naked_empty()
// FIXME(#39685) Avoid one block per call.
// CHECK-NEXT: br label %bb1
naked_empty();
- // CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return()
+ // CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return()
// FIXME(#39685) Avoid one block per call.
// CHECK-NEXT: br label %bb2
// CHECK: bb2:
- // CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}})
+ // CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}})
// FIXME(#39685) Avoid one block per call.
// CHECK-NEXT: br label %bb3
// CHECK: bb3:
- // CHECK: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}})
+ // CHECK-NEXT: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}})
// FIXME(#39685) Avoid one block per call.
// CHECK-NEXT: br label %bb4
-// compile-flags: -C opt-level=3
+// compile-flags: -C opt-level=3 -Z insert-sideeffect
#![crate_type = "lib"]
-// compile-flags: -C opt-level=3
+// compile-flags: -C opt-level=3 -Z insert-sideeffect
#![crate_type = "lib"]
-// compile-flags: -C opt-level=3
+// compile-flags: -C opt-level=3 -Z insert-sideeffect
#![crate_type = "lib"]
// CHECK-LABEL: @repeat_take_collect
#[no_mangle]
pub fn repeat_take_collect() -> Vec<u8> {
-// FIXME: At the time of writing LLVM transforms this loop into a single
-// `store` and then a `memset` with size = 99999. The correct check should be:
-// call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[a-z0-9.]+}}, i8 42, [[USIZE]] 100000, i1 false)
-
-// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[a-z0-9.]+}}, i8 42, [[USIZE]] 99999, i1 false)
+// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false)
iter::repeat(42).take(100000).collect()
}
-// ignore-test
-
-// FIXME:
-// LLVM can't optimize some loops with unknown number of iterations because of
-// @llvm.sideeffect() (see also #59546)
-
// ignore-debug: the debug assertions get in the way
// compile-flags: -O
#[no_mangle]
pub fn get_len() -> usize {
- // CHECK-COUNT-1: {{^define}}
+ // CHECK-LABEL: @get_len
+ // CHECK-NOT: call
+ // CHECK-NOT: invoke
[1, 2, 3].iter().collect::<Vec<_>>().len()
}
pub fn sum_me() -> i32 {
// CHECK-LABEL: @sum_me
// CHECK-NEXT: {{^.*:$}}
- // CHECK: ret i32 6
+ // CHECK-NEXT: ret i32 6
vec![1, 2, 3].iter().sum::<i32>()
}
all:
$(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2
- if cat $(TMPDIR)/*.ll | grep -v 'call void @llvm.sideeffect()' | $(CGREP) -e '\bcall\b'; then \
+ if cat $(TMPDIR)/*.ll | $(CGREP) -e '\bcall\b'; then \
echo "found call instruction when one wasn't expected"; \
exit 1; \
fi