Index: llvm/test/Transforms/GVN/simple-gvnhoist-loadstore.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/GVN/simple-gvnhoist-loadstore.ll @@ -0,0 +1,801 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S --aa-pipeline=tbaa,basic-aa --passes=gvn %s | FileCheck %s + +define dso_local i32 @basic_load_hoisting(i1 %cc, i32* %a, i32 %b, i32 %c) { +; CHECK-LABEL: @basic_load_hoisting( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[TMP0]], [[B:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = sdiv i32 [[C:%.*]], [[TMP1]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[A]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = add nsw i32 [[TMP3]], [[B]] +; CHECK-NEXT: [[TMP5:%.*]] = sdiv i32 [[C]], [[TMP4]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP2]], [[IF_THEN]] ], [ [[TMP5]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load i32, i32* %a + %1 = add nsw i32 %0, %b + %2 = sdiv i32 %c, %1 + br label %if.end + +if.else: + %3 = load i32, i32* %a + %4 = add nsw i32 %3, %b + %5 = sdiv i32 %c, %4 + br label %if.end + +if.end: + %r = phi i32 [%2, %if.then], [%5, %if.else] + ret i32 %r +} + +define dso_local i32 @hoist_volatile(i1 %cc, i32* %a) { +; CHECK-LABEL: @hoist_volatile( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load volatile i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP1:%.*]] = load volatile i32, i32* [[A]], align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP1]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load volatile i32, i32* %a + br label %if.end + +if.else: + %1 = load volatile i32, i32* %a + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%1, %if.else] + ret i32 %r +} + +define dso_local i32 @no_merge_volatile_with_non_volatile(i1 %cc, i32* %a) { +; CHECK-LABEL: @no_merge_volatile_with_non_volatile( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP1:%.*]] = load volatile i32, i32* [[A]], align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP1]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load i32, i32* %a + br label %if.end + +if.else: + %1 = load volatile i32, i32* %a + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%1, %if.else] + ret i32 %r +} + +define dso_local i32 @hoist_atomic(i1 %cc, i32* %a) { +; CHECK-LABEL: @hoist_atomic( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load atomic i32, i32* [[A:%.*]] acquire, align 4 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP1:%.*]] = load atomic i32, i32* [[A]] acquire, align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP1]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load atomic i32, i32* %a acquire, align 4 + br label %if.end + +if.else: + %1 = load atomic i32, i32* %a acquire, align 4 + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%1, %if.else] + ret i32 %r +} + +define dso_local i32 @no_merge_atomic_different_ordering0(i1 %cc, i32* %a) { +; CHECK-LABEL: @no_merge_atomic_different_ordering0( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP1:%.*]] = load atomic i32, i32* [[A]] acquire, align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP1]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load i32, i32* %a, align 4 + br label %if.end + +if.else: + %1 = load atomic i32, i32* %a acquire, align 4 + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%1, %if.else] + ret i32 %r +} + +define dso_local i32 @no_merge_atomic_different_ordering1(i1 %cc, i32* %a) { +; CHECK-LABEL: @no_merge_atomic_different_ordering1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load atomic i32, i32* [[A:%.*]] acquire, align 4 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP1:%.*]] = load atomic i32, i32* [[A]] monotonic, align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP1]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load atomic i32, i32* %a acquire, align 4 + br label %if.end + +if.else: + %1 = load atomic i32, i32* %a monotonic, align 4 + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%1, %if.else] + ret i32 %r +} + +define dso_local i32 @no_reorder_load_over_aliasing_store0(i1 %cc, i32* %a, i32* %b) { +; CHECK-LABEL: @no_reorder_load_over_aliasing_store0( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* [[B:%.*]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[A]], align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP1]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + store i32 0, i32* %b + %0 = load i32, i32* %a + br label %if.end + +if.else: + %1 = load i32, i32* %a + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%1, %if.else] + ret i32 %r +} + +define dso_local i32 @no_reorder_load_over_aliasing_store1(i1 %cc, i32* %a, i32* %b, i32* %c, i32 %d, i32 %e) { +; CHECK-LABEL: @no_reorder_load_over_aliasing_store1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* [[C:%.*]], align 4, !tbaa [[TBAA0:![0-9]+]] +; CHECK-NEXT: store i32 0, i32* [[B:%.*]], align 4, !tbaa [[TBAA4:![0-9]+]] +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4, !tbaa [[TBAA6:![0-9]+]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: store i32 0, i32* [[B]], align 4, !tbaa [[TBAA4]] +; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[A]], align 4, !tbaa [[TBAA6]] +; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], [[D:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], [[E:%.*]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP3]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + store i32 0, i32* %c, !tbaa !6 + store i32 0, i32* %b, !tbaa !5 + %0 = load i32, i32* %a, !tbaa !4 + br label %if.end + +if.else: + store i32 0, i32* %b, !tbaa !5 + %1 = load i32, i32* %a, !tbaa !4 + %2 = add i32 %1, %d + %3 = add i32 %2, %e + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%3, %if.else] + ret i32 %r +} + +define dso_local i32 @reorder_non_volatile(i1 %cc, i32* %a, i32* %b, i32 %c) { +; CHECK-LABEL: @reorder_non_volatile( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B:%.*]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP0]], [[TMP1]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP3:%.*]] = load volatile i32, i32* [[B]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[A]], align 4 +; CHECK-NEXT: [[TMP5:%.*]] = add nsw i32 [[TMP3]], [[TMP4]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP2]], [[IF_THEN]] ], [ [[TMP5]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load i32, i32* %a + %1 = load i32, i32* %b + %2 = add nsw i32 %0, %1 + br label %if.end + +if.else: + %3 = load volatile i32, i32* %b + %4 = load i32, i32* %a + %5 = add nsw i32 %3, %4 + br label %if.end + +if.end: + %r = phi i32 [%2, %if.then], [%5, %if.else] + ret i32 %r +} + +define dso_local i32 @no_reorder_volatile(i1 %cc, i32* %a, i32* %b, i32 %c) { +; CHECK-LABEL: @no_reorder_volatile( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load volatile i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = load volatile i32, i32* [[B:%.*]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP0]], [[TMP1]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP3:%.*]] = load volatile i32, i32* [[B]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = load volatile i32, i32* [[A]], align 4 +; CHECK-NEXT: [[TMP5:%.*]] = add nsw i32 [[TMP3]], [[TMP4]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP2]], [[IF_THEN]] ], [ [[TMP5]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load volatile i32, i32* %a + %1 = load volatile i32, i32* %b + %2 = add nsw i32 %0, %1 + br label %if.end + +if.else: + %3 = load volatile i32, i32* %b + %4 = load volatile i32, i32* %a + %5 = add nsw i32 %3, %4 + br label %if.end + +if.end: + %r = phi i32 [%2, %if.then], [%5, %if.else] + ret i32 %r +} + +define dso_local i32 @no_reorder_atomic0(i1 %cc, i32* %a, i32* %b, i32 %c) { +; CHECK-LABEL: @no_reorder_atomic0( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B:%.*]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP0]], [[TMP1]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP3:%.*]] = load atomic i32, i32* [[B]] acquire, align 4 +; CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[A]], align 4 +; CHECK-NEXT: [[TMP5:%.*]] = add nsw i32 [[TMP3]], [[TMP4]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP2]], [[IF_THEN]] ], [ [[TMP5]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load i32, i32* %a + %1 = load i32, i32* %b + %2 = add nsw i32 %0, %1 + br label %if.end + +if.else: + %3 = load atomic i32, i32* %b acquire, align 4 + %4 = load i32, i32* %a + %5 = add nsw i32 %3, %4 + br label %if.end + +if.end: + %r = phi i32 [%2, %if.then], [%5, %if.else] + ret i32 %r +} + +define dso_local i32 @no_reorder_atomic1(i1 %cc, i32* %a, i32* %b, i32 %c) { +; CHECK-LABEL: @no_reorder_atomic1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load atomic i32, i32* [[A:%.*]] acquire, align 4 +; CHECK-NEXT: [[TMP1:%.*]] = load atomic i32, i32* [[B:%.*]] acquire, align 4 +; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP0]], [[TMP1]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP3:%.*]] = load atomic i32, i32* [[A]] acquire, align 4 +; CHECK-NEXT: [[TMP4:%.*]] = load atomic i32, i32* [[B]] acquire, align 4 +; CHECK-NEXT: [[TMP5:%.*]] = add nsw i32 [[TMP3]], [[TMP4]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP2]], [[IF_THEN]] ], [ [[TMP5]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load atomic i32, i32* %a acquire, align 4 + %1 = load atomic i32, i32* %b acquire, align 4 + %2 = add nsw i32 %0, %1 + br label %if.end + +if.else: + %3 = load atomic i32, i32* %a acquire, align 4 + %4 = load atomic i32, i32* %b acquire, align 4 + %5 = add nsw i32 %3, %4 + br label %if.end + +if.end: + %r = phi i32 [%2, %if.then], [%5, %if.else] + ret i32 %r +} + +define dso_local i32 @reorder_load_over_non_aliasing_store(i1 %cc, i32* %a, i32 %b, i32 %c, i32* %p) { +; CHECK-LABEL: @reorder_load_over_non_aliasing_store( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4, !tbaa [[TBAA4]] +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[TMP0]], [[B:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = sdiv i32 [[C:%.*]], [[TMP0]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[A]], align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: [[TMP4:%.*]] = add nsw i32 [[TMP3]], [[B]] +; CHECK-NEXT: [[TMP5:%.*]] = sdiv i32 [[C]], [[TMP4]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP2]], [[IF_THEN]] ], [ [[TMP5]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + store i32 0, i32* %p, !tbaa !5 + %0 = load i32, i32* %a, !tbaa !6 + %1 = add nsw i32 %0, %b + %2 = sdiv i32 %c, %0 + br label %if.end + +if.else: + %3 = load i32, i32* %a, !tbaa !6 + %4 = add nsw i32 %3, %b + %5 = sdiv i32 %c, %4 + br label %if.end + +if.end: + %r = phi i32 [%2, %if.then], [%5, %if.else] + ret i32 %r +} + +define dso_local i32 @load_phi_dep(i1 %cc0, i1 %cc1, i32* %a, i32 %b, i32* %p) { +; CHECK-LABEL: @load_phi_dep( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC0:%.*]], label [[IF_THEN0:%.*]], label [[IF_ELSE0:%.*]] +; CHECK: if.then0: +; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4 +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: if.else0: +; CHECK-NEXT: br label [[BB]] +; CHECK: bb: +; CHECK-NEXT: br i1 [[CC1:%.*]], label [[IF_THEN1:%.*]], label [[IF_ELSE1:%.*]] +; CHECK: if.then1: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[TMP0]], [[B:%.*]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else1: +; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[A]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = add nsw i32 [[TMP2]], [[B]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP1]], [[IF_THEN1]] ], [ [[TMP3]], [[IF_ELSE1]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc0, label %if.then0, label %if.else0 + +if.then0: + store i32 0, i32* %p + br label %bb + +if.else0: + br label %bb + +bb: + br i1 %cc1, label %if.then1, label %if.else1 + +if.then1: + %0 = load i32, i32* %a + %1 = add nsw i32 %0, %b + br label %if.end + +if.else1: + %2 = load i32, i32* %a + %3 = add nsw i32 %2, %b + br label %if.end + +if.end: + %r = phi i32 [%1, %if.then1], [%3, %if.else1] + ret i32 %r +} + +define dso_local i32 @host_store0(i1 %cc, i32* %a, i32 %b, i32* %p) { +; CHECK-LABEL: @host_store0( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[B:%.*]], 1 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: store i32 0, i32* [[P]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[B]], [[TMP1]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP2]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + store i32 0, i32* %p + %0 = add nsw i32 %b, 1 + br label %if.end + +if.else: + store i32 0, i32* %p + %1 = load i32, i32* %a + %2 = add nsw i32 %b, %1 + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%2, %if.else] + ret i32 %r +} + +define dso_local i32 @host_store1(i1 %cc, i32* %a, i32 %b, i32* %p) { +; CHECK-LABEL: @host_store1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 1, i32* [[A:%.*]], align 4 +; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[B:%.*]], 1 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: store i32 1, i32* [[A]], align 4 +; CHECK-NEXT: store i32 0, i32* [[P]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[A]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[B]], [[TMP1]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP2]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + store i32 1, i32* %a + store i32 0, i32* %p + %0 = add nsw i32 %b, 1 + br label %if.end + +if.else: + store i32 1, i32* %a + store i32 0, i32* %p + %1 = load i32, i32* %a + %2 = add nsw i32 %b, %1 + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%2, %if.else] + ret i32 %r +} + +define dso_local void @no_store_reorder_across_aliasing_store0(i1 %cc, i32* %a, i32* %b) { +; CHECK-LABEL: @no_store_reorder_across_aliasing_store0( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* [[A:%.*]], align 4 +; CHECK-NEXT: store i32 0, i32* [[B:%.*]], align 4 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: store i32 0, i32* [[B]], align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: ret void +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + store i32 0, i32* %a + store i32 0, i32* %b + br label %if.end + +if.else: + store i32 0, i32* %b + br label %if.end + +if.end: + ret void +} + +define dso_local i32 @no_store_reorder_across_aliasing_store1(i1 %cc, i32* %a, i32* %b, i32* %c) { +; CHECK-LABEL: @no_store_reorder_across_aliasing_store1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* [[B:%.*]], align 4 +; CHECK-NEXT: store i32 1, i32* [[A:%.*]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[C:%.*]], align 4 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: store i32 1, i32* [[A]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[C]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], 1 +; CHECK-NEXT: [[TMP3:%.*]] = mul nsw i32 [[TMP2]], 2 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP3]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + store i32 0, i32* %b + store i32 1, i32* %a + %0 = load i32, i32* %c + br label %if.end + +if.else: + store i32 1, i32* %a + %1 = load i32, i32* %c + %2 = add nsw i32 %1, 1 + %3 = mul nsw i32 %2, 2 + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%3, %if.else] + ret i32 %r +} + +define dso_local i32 @no_store_reorder_across_aliasing_load0(i1 %cc, i32* %a, i32 %b, i32* %p) { +; CHECK-LABEL: @no_store_reorder_across_aliasing_load0( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[B:%.*]], 1 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: store i32 0, i32* [[P]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], [[B]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP2]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + store i32 0, i32* %p + %0 = add nsw i32 %b, 1 + br label %if.end + +if.else: + %1 = load i32, i32* %a + store i32 0, i32* %p + %2 = add nsw i32 %1, %b + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%2, %if.else] + ret i32 %r +} + +define dso_local i32 @no_store_reorder_across_aliasing_load1(i1 %cc, i32* %a, i32* %b, i32* %p) { +; CHECK-LABEL: @no_store_reorder_across_aliasing_load1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4 +; CHECK-NEXT: store i32 0, i32* [[P:%.*]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[TMP0]], 1 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[A]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[B:%.*]], align 4 +; CHECK-NEXT: store i32 0, i32* [[P]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = add nsw i32 [[TMP2]], [[TMP3]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP1]], [[IF_THEN]] ], [ [[TMP4]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load i32, i32* %a + store i32 0, i32* %p + %1 = add nsw i32 %0, 1 + br label %if.end + +if.else: + %2 = load i32, i32* %a + %3 = load i32, i32* %b + store i32 0, i32* %p + %4 = add nsw i32 %2, %3 + br label %if.end + +if.end: + %r = phi i32 [%1, %if.then], [%4, %if.else] + ret i32 %r +} + +define dso_local void @store_reorder_across_nonaliasing_store(i1 %cc, i32* %b, i32* %c) { +; CHECK-LABEL: @store_reorder_across_nonaliasing_store( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* [[B:%.*]], align 4, !tbaa [[TBAA4]] +; CHECK-NEXT: store i32 1, i32* [[C:%.*]], align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: store i32 1, i32* [[C]], align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: store i32 0, i32* [[B]], align 4, !tbaa [[TBAA4]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: ret void +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + store i32 0, i32* %b, !tbaa !5 + store i32 1, i32* %c, !tbaa !6 + br label %if.end + +if.else: + store i32 1, i32* %c, !tbaa !6 + store i32 0, i32* %b, !tbaa !5 + br label %if.end + +if.end: + ret void +} + +define dso_local i32 @store_reorder_across_nonaliasing_load(i1 %cc, i32* %b, i32* %c) { +; CHECK-LABEL: @store_reorder_across_nonaliasing_load( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[B:%.*]], align 4, !tbaa [[TBAA4]] +; CHECK-NEXT: store i32 1, i32* [[C:%.*]], align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: store i32 1, i32* [[C]], align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP1]], [[IF_ELSE]] ] +; CHECK-NEXT: ret i32 [[R]] +; +entry: + br i1 %cc, label %if.then, label %if.else + +if.then: + %0 = load i32, i32* %b, !tbaa !5 + store i32 1, i32* %c, !tbaa !6 + br label %if.end + +if.else: + store i32 1, i32* %c, !tbaa !6 + %1 = load i32, i32* %b + br label %if.end + +if.end: + %r = phi i32 [%0, %if.then], [%1, %if.else] + ret i32 %r +} + +!0 = !{!"TBAA"} +!1 = !{!"A", !0, i64 0} +!2 = !{!"B", !1, i64 0} +!3 = !{!"C", !1, i64 0} +!4 = !{!1, !1, i64 0} +!5 = !{!2, !2, i64 0} +!6 = !{!3, !3, i64 0}