https://github.com/momchil-velikov created 
https://github.com/llvm/llvm-project/pull/210336

None

>From 12654f87243c8ec685d68442622bfd3e87e51873 Mon Sep 17 00:00:00 2001
From: Momchil Velikov <[email protected]>
Date: Fri, 10 Jul 2026 13:54:09 +0100
Subject: [PATCH] [GVN] Simple GVN-based hoisting of scalars: precommit tests

---
 .../Transforms/GVN/simple-gvn-hoist-limits.ll | 155 +++++++
 .../GVN/simple-gvn-hoist-scalars.ll           | 382 ++++++++++++++++++
 2 files changed, 537 insertions(+)
 create mode 100644 llvm/test/Transforms/GVN/simple-gvn-hoist-limits.ll
 create mode 100644 llvm/test/Transforms/GVN/simple-gvn-hoist-scalars.ll

diff --git a/llvm/test/Transforms/GVN/simple-gvn-hoist-limits.ll 
b/llvm/test/Transforms/GVN/simple-gvn-hoist-limits.ll
new file mode 100644
index 0000000000000..0c0789e6e4144
--- /dev/null
+++ b/llvm/test/Transforms/GVN/simple-gvn-hoist-limits.ll
@@ -0,0 +1,155 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S --passes=gvn --gvn-max-num-insns=3 %s -o - | FileCheck %s 
--check-prefix=MAX-DEPTH3
+; RUN: opt -S --passes=gvn --gvn-max-num-insns=4 %s -o - | FileCheck %s 
--check-prefix=MAX-DEPTH4
+; RUN: opt -S --passes=gvn --gvn-max-num-insns=5 %s -o - | FileCheck %s 
--check-prefix=MAX-DEPTH5
+
+; Check effect of limiting the how deep in a block we look for
+; instructions to hoist; At max depth 3 we shouldn't hoist
+; anything to the `entry` block, at max depth 4 we should hoist
+; the first `add` and at max depth 5 the second `add`.
+
+; In any case we shouldn't hoist the `and` and the `icmp`, in order
+; to not separate them from the `br`
+
+define i32 @f(i1 %c, i32 %a, i32 %b, i32 %d) {
+; MAX-DEPTH3-LABEL: @f(
+; MAX-DEPTH3-NEXT:  entry:
+; MAX-DEPTH3-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label 
[[IF_ELSE:%.*]]
+; MAX-DEPTH3:       if.then:
+; MAX-DEPTH3-NEXT:    [[R0:%.*]] = add i32 [[B:%.*]], 1
+; MAX-DEPTH3-NEXT:    [[AND0:%.*]] = and i32 [[A:%.*]], 1
+; MAX-DEPTH3-NEXT:    [[TOBOOL_AND0:%.*]] = icmp eq i32 [[AND0]], 0
+; MAX-DEPTH3-NEXT:    [[D0:%.*]] = add i32 [[D:%.*]], 1
+; MAX-DEPTH3-NEXT:    [[S0:%.*]] = add i32 [[D0]], [[B]]
+; MAX-DEPTH3-NEXT:    br i1 [[TOBOOL_AND0]], label [[IF_THEN1:%.*]], label 
[[IF_ELSE1:%.*]]
+; MAX-DEPTH3:       if.then1:
+; MAX-DEPTH3-NEXT:    [[OR0:%.*]] = or i32 [[R0]], 1
+; MAX-DEPTH3-NEXT:    br label [[EXIT:%.*]]
+; MAX-DEPTH3:       if.else1:
+; MAX-DEPTH3-NEXT:    [[OR1:%.*]] = or i32 [[R0]], 2
+; MAX-DEPTH3-NEXT:    br label [[EXIT]]
+; MAX-DEPTH3:       if.else:
+; MAX-DEPTH3-NEXT:    [[R1:%.*]] = add i32 [[B]], 2
+; MAX-DEPTH3-NEXT:    [[AND1:%.*]] = and i32 [[A]], 1
+; MAX-DEPTH3-NEXT:    [[TOBOOL_AND1:%.*]] = icmp eq i32 [[AND1]], 0
+; MAX-DEPTH3-NEXT:    [[D1:%.*]] = add i32 [[D]], 1
+; MAX-DEPTH3-NEXT:    [[S1:%.*]] = add i32 [[D1]], [[B]]
+; MAX-DEPTH3-NEXT:    br i1 [[TOBOOL_AND1]], label [[IF_THEN2:%.*]], label 
[[IF_ELSE2:%.*]]
+; MAX-DEPTH3:       if.then2:
+; MAX-DEPTH3-NEXT:    [[OR2:%.*]] = or i32 [[R1]], 4
+; MAX-DEPTH3-NEXT:    br label [[EXIT]]
+; MAX-DEPTH3:       if.else2:
+; MAX-DEPTH3-NEXT:    [[OR3:%.*]] = or i32 [[R1]], 8
+; MAX-DEPTH3-NEXT:    br label [[EXIT]]
+; MAX-DEPTH3:       exit:
+; MAX-DEPTH3-NEXT:    [[OR:%.*]] = phi i32 [ [[OR0]], [[IF_THEN1]] ], [ 
[[OR1]], [[IF_ELSE1]] ], [ [[OR2]], [[IF_THEN2]] ], [ [[OR3]], [[IF_ELSE2]] ]
+; MAX-DEPTH3-NEXT:    [[S:%.*]] = phi i32 [ [[S0]], [[IF_THEN1]] ], [ [[S0]], 
[[IF_ELSE1]] ], [ [[S1]], [[IF_THEN2]] ], [ [[S1]], [[IF_ELSE2]] ]
+; MAX-DEPTH3-NEXT:    [[R:%.*]] = add i32 [[OR]], [[S]]
+; MAX-DEPTH3-NEXT:    ret i32 [[R]]
+;
+; MAX-DEPTH4-LABEL: @f(
+; MAX-DEPTH4-NEXT:  entry:
+; MAX-DEPTH4-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label 
[[IF_ELSE:%.*]]
+; MAX-DEPTH4:       if.then:
+; MAX-DEPTH4-NEXT:    [[R0:%.*]] = add i32 [[B:%.*]], 1
+; MAX-DEPTH4-NEXT:    [[AND0:%.*]] = and i32 [[A:%.*]], 1
+; MAX-DEPTH4-NEXT:    [[TOBOOL_AND0:%.*]] = icmp eq i32 [[AND0]], 0
+; MAX-DEPTH4-NEXT:    [[D0:%.*]] = add i32 [[D:%.*]], 1
+; MAX-DEPTH4-NEXT:    [[S0:%.*]] = add i32 [[D0]], [[B]]
+; MAX-DEPTH4-NEXT:    br i1 [[TOBOOL_AND0]], label [[IF_THEN1:%.*]], label 
[[IF_ELSE1:%.*]]
+; MAX-DEPTH4:       if.then1:
+; MAX-DEPTH4-NEXT:    [[OR0:%.*]] = or i32 [[R0]], 1
+; MAX-DEPTH4-NEXT:    br label [[EXIT:%.*]]
+; MAX-DEPTH4:       if.else1:
+; MAX-DEPTH4-NEXT:    [[OR1:%.*]] = or i32 [[R0]], 2
+; MAX-DEPTH4-NEXT:    br label [[EXIT]]
+; MAX-DEPTH4:       if.else:
+; MAX-DEPTH4-NEXT:    [[R1:%.*]] = add i32 [[B]], 2
+; MAX-DEPTH4-NEXT:    [[AND1:%.*]] = and i32 [[A]], 1
+; MAX-DEPTH4-NEXT:    [[TOBOOL_AND1:%.*]] = icmp eq i32 [[AND1]], 0
+; MAX-DEPTH4-NEXT:    [[D1:%.*]] = add i32 [[D]], 1
+; MAX-DEPTH4-NEXT:    [[S1:%.*]] = add i32 [[D1]], [[B]]
+; MAX-DEPTH4-NEXT:    br i1 [[TOBOOL_AND1]], label [[IF_THEN2:%.*]], label 
[[IF_ELSE2:%.*]]
+; MAX-DEPTH4:       if.then2:
+; MAX-DEPTH4-NEXT:    [[OR2:%.*]] = or i32 [[R1]], 4
+; MAX-DEPTH4-NEXT:    br label [[EXIT]]
+; MAX-DEPTH4:       if.else2:
+; MAX-DEPTH4-NEXT:    [[OR3:%.*]] = or i32 [[R1]], 8
+; MAX-DEPTH4-NEXT:    br label [[EXIT]]
+; MAX-DEPTH4:       exit:
+; MAX-DEPTH4-NEXT:    [[OR:%.*]] = phi i32 [ [[OR0]], [[IF_THEN1]] ], [ 
[[OR1]], [[IF_ELSE1]] ], [ [[OR2]], [[IF_THEN2]] ], [ [[OR3]], [[IF_ELSE2]] ]
+; MAX-DEPTH4-NEXT:    [[S:%.*]] = phi i32 [ [[S0]], [[IF_THEN1]] ], [ [[S0]], 
[[IF_ELSE1]] ], [ [[S1]], [[IF_THEN2]] ], [ [[S1]], [[IF_ELSE2]] ]
+; MAX-DEPTH4-NEXT:    [[R:%.*]] = add i32 [[OR]], [[S]]
+; MAX-DEPTH4-NEXT:    ret i32 [[R]]
+;
+; MAX-DEPTH5-LABEL: @f(
+; MAX-DEPTH5-NEXT:  entry:
+; MAX-DEPTH5-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label 
[[IF_ELSE:%.*]]
+; MAX-DEPTH5:       if.then:
+; MAX-DEPTH5-NEXT:    [[R0:%.*]] = add i32 [[B:%.*]], 1
+; MAX-DEPTH5-NEXT:    [[AND0:%.*]] = and i32 [[A:%.*]], 1
+; MAX-DEPTH5-NEXT:    [[TOBOOL_AND0:%.*]] = icmp eq i32 [[AND0]], 0
+; MAX-DEPTH5-NEXT:    [[D0:%.*]] = add i32 [[D:%.*]], 1
+; MAX-DEPTH5-NEXT:    [[S0:%.*]] = add i32 [[D0]], [[B]]
+; MAX-DEPTH5-NEXT:    br i1 [[TOBOOL_AND0]], label [[IF_THEN1:%.*]], label 
[[IF_ELSE1:%.*]]
+; MAX-DEPTH5:       if.then1:
+; MAX-DEPTH5-NEXT:    [[OR0:%.*]] = or i32 [[R0]], 1
+; MAX-DEPTH5-NEXT:    br label [[EXIT:%.*]]
+; MAX-DEPTH5:       if.else1:
+; MAX-DEPTH5-NEXT:    [[OR1:%.*]] = or i32 [[R0]], 2
+; MAX-DEPTH5-NEXT:    br label [[EXIT]]
+; MAX-DEPTH5:       if.else:
+; MAX-DEPTH5-NEXT:    [[R1:%.*]] = add i32 [[B]], 2
+; MAX-DEPTH5-NEXT:    [[AND1:%.*]] = and i32 [[A]], 1
+; MAX-DEPTH5-NEXT:    [[TOBOOL_AND1:%.*]] = icmp eq i32 [[AND1]], 0
+; MAX-DEPTH5-NEXT:    [[D1:%.*]] = add i32 [[D]], 1
+; MAX-DEPTH5-NEXT:    [[S1:%.*]] = add i32 [[D1]], [[B]]
+; MAX-DEPTH5-NEXT:    br i1 [[TOBOOL_AND1]], label [[IF_THEN2:%.*]], label 
[[IF_ELSE2:%.*]]
+; MAX-DEPTH5:       if.then2:
+; MAX-DEPTH5-NEXT:    [[OR2:%.*]] = or i32 [[R1]], 4
+; MAX-DEPTH5-NEXT:    br label [[EXIT]]
+; MAX-DEPTH5:       if.else2:
+; MAX-DEPTH5-NEXT:    [[OR3:%.*]] = or i32 [[R1]], 8
+; MAX-DEPTH5-NEXT:    br label [[EXIT]]
+; MAX-DEPTH5:       exit:
+; MAX-DEPTH5-NEXT:    [[OR:%.*]] = phi i32 [ [[OR0]], [[IF_THEN1]] ], [ 
[[OR1]], [[IF_ELSE1]] ], [ [[OR2]], [[IF_THEN2]] ], [ [[OR3]], [[IF_ELSE2]] ]
+; MAX-DEPTH5-NEXT:    [[S:%.*]] = phi i32 [ [[S0]], [[IF_THEN1]] ], [ [[S0]], 
[[IF_ELSE1]] ], [ [[S1]], [[IF_THEN2]] ], [ [[S1]], [[IF_ELSE2]] ]
+; MAX-DEPTH5-NEXT:    [[R:%.*]] = add i32 [[OR]], [[S]]
+; MAX-DEPTH5-NEXT:    ret i32 [[R]]
+;
+entry:
+  br i1 %c, label %if.then, label %if.else
+
+if.then:
+  %r0 = add i32 %b, 1
+  %and0 = and i32 %a, 1
+  %tobool.and0 = icmp eq i32 %and0, 0
+  %d0 = add i32 %d, 1
+  %s0 = add i32 %d0, %b
+  br i1 %tobool.and0, label %if.then1, label %if.else1
+if.then1:
+  %or0 = or i32 %r0, 1
+  br label %exit
+if.else1:
+  %or1 = or i32 %r0, 2
+  br label %exit
+
+if.else:
+  %r1 = add i32 %b, 2
+  %and1 = and i32 %a, 1
+  %tobool.and1 = icmp eq i32 %and1, 0
+  %d1 = add i32 %d, 1
+  %s1 = add i32 %d1, %b
+  br i1 %tobool.and1, label %if.then2, label %if.else2
+if.then2:
+  %or2 = or i32 %r1, 4
+  br label %exit
+if.else2:
+  %or3 = or i32 %r1, 8
+  br label %exit
+exit:
+  %or = phi i32 [%or0, %if.then1], [%or1, %if.else1], [%or2, %if.then2], 
[%or3, %if.else2]
+  %s = phi i32 [%s0, %if.then1], [%s0, %if.else1], [%s1, %if.then2], [%s1, 
%if.else2]
+  %r = add i32 %or, %s
+  ret i32 %r
+}
diff --git a/llvm/test/Transforms/GVN/simple-gvn-hoist-scalars.ll 
b/llvm/test/Transforms/GVN/simple-gvn-hoist-scalars.ll
new file mode 100644
index 0000000000000..e774f64d4a4e5
--- /dev/null
+++ b/llvm/test/Transforms/GVN/simple-gvn-hoist-scalars.ll
@@ -0,0 +1,382 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt --passes=gvn -S %s | FileCheck %s
+; RUN: opt --passes="gvn<memoryssa>" -S %s | FileCheck %s
+
+target triple = "aarch64-unknown-linux"
+
+define dso_local i32 @everything_hoisted(i1 %cc, i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @everything_hoisted(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @barrier(i32 [[A:%.*]])
+; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[TMP0]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = sdiv i32 [[TMP1]], [[C:%.*]]
+; CHECK-NEXT:    br label [[IF_END:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[TMP3:%.*]] = call i32 @barrier(i32 [[A]])
+; CHECK-NEXT:    [[TMP4:%.*]] = add i32 [[TMP3]], [[B]]
+; CHECK-NEXT:    [[TMP5:%.*]] = sdiv i32 [[TMP4]], [[C]]
+; 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 = call i32 @barrier(i32 %a)
+  %1 = add i32 %0, %b
+  %2 = sdiv i32 %1, %c
+  br label %if.end
+
+if.else:
+  %3 = call i32 @barrier(i32 %a)
+  %4 = add i32 %3, %b
+  %5 = sdiv i32 %4, %c
+  br label %if.end
+
+if.end:
+  %r = phi i32 [%2, %if.then], [%5, %if.else]
+  ret i32 %r
+}
+
+; speculation barrier on the short(collect) side
+define dso_local i32 @spec_barrier_short_side(i1 %cc, i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @spec_barrier_short_side(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @barrier(i32 [[A:%.*]])
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[A]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sdiv i32 [[C:%.*]], [[TMP0]]
+; CHECK-NEXT:    br label [[IF_END:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[TMP6:%.*]] = add nsw i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP3:%.*]] = sdiv i32 [[C]], [[TMP6]]
+; CHECK-NEXT:    [[TMP5:%.*]] = add i32 [[TMP3]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = add i32 [[TMP5]], 2
+; 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 = call i32 @barrier(i32 %a)
+  %1 = add nsw i32 %a, %b
+  %2 = sdiv i32 %c, %1
+  br label %if.end
+
+if.else:
+  %3 = add nsw i32 %a, %b
+  %4 = sdiv i32 %c, %3
+  %5 = add i32 %4, 1
+  %6 = add i32 %5, 2
+  br label %if.end
+
+if.end:
+  %r = phi i32 [%2, %if.then], [%6, %if.else]
+  ret i32 %r
+}
+
+; speculation barrier on the long(match) side
+define dso_local i32 @spec_barrier_long_side(i1 %cc, i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @spec_barrier_long_side(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sdiv i32 [[C:%.*]], [[TMP0]]
+; CHECK-NEXT:    br label [[IF_END:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @barrier(i32 [[A]])
+; CHECK-NEXT:    [[TMP6:%.*]] = add nsw i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP3:%.*]] = sdiv i32 [[C]], [[TMP6]]
+; CHECK-NEXT:    [[TMP5:%.*]] = add i32 [[TMP3]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = add i32 [[TMP5]], 2
+; 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 = add nsw i32 %a, %b
+  %1 = sdiv i32 %c, %0
+  br label %if.end
+
+if.else:
+  %2 = call i32 @barrier(i32 %a)
+  %3 = add nsw i32 %a, %b
+  %4 = sdiv i32 %c, %3
+  %5 = add i32 %4, 1
+  %6 = add i32 %5, 2
+  br label %if.end
+
+if.end:
+  %r = phi i32 [%1, %if.then], [%6, %if.else]
+  ret i32 %r
+}
+
+define dso_local i32 @no_reorder_across_volatile(i1 %cc, i32 %a, i32 %b, i32 
%c, ptr %p) {
+; CHECK-LABEL: @no_reorder_across_volatile(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = sdiv i32 [[C:%.*]], [[TMP0]]
+; CHECK-NEXT:    br label [[IF_END:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    store volatile i32 0, ptr [[P:%.*]], align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP2:%.*]] = sdiv i32 [[C]], [[TMP3]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[TMP1]], [[IF_THEN]] ], [ [[TMP2]], 
[[IF_ELSE]] ]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+entry:
+  br i1 %cc, label %if.then, label %if.else
+
+if.then:
+  %0 = add nsw i32 %a, %b
+  %1 = sdiv i32 %c, %0
+  br label %if.end
+
+if.else:
+  store volatile i32 0, ptr %p
+  %2 = add nsw i32 %a, %b
+  %3 = sdiv i32 %c, %2
+  br label %if.end
+
+if.end:
+  %r = phi i32 [%1, %if.then], [%3, %if.else]
+  ret i32 %r
+}
+
+define dso_local i32 @no_barrier_call(i1 %cc, i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @no_barrier_call(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    call void @will_return()
+; CHECK-NEXT:    [[TMP0:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add nsw i32 [[C:%.*]], [[TMP0]]
+; CHECK-NEXT:    br label [[IF_END:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    call void @will_return()
+; CHECK-NEXT:    [[TMP2:%.*]] = sdiv i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i32 [[C]], [[TMP2]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[TMP1]], [[IF_THEN]] ], [ [[TMP3]], 
[[IF_ELSE]] ]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+entry:
+  br i1 %cc, label %if.then, label %if.else
+
+if.then:
+  call void @will_return()
+  %0 = sdiv i32 %a, %b
+  %1 = add nsw i32 %c, %0
+  br label %if.end
+
+if.else:
+  call void @will_return()
+  %2 = sdiv i32 %a, %b
+  %3 = add nsw i32 %c, %2
+  br label %if.end
+
+if.end:
+  %r = phi i32 [%1, %if.then], [%3, %if.else]
+  ret i32 %r
+}
+
+define dso_local i32 @no_reorder_atomic(i1 %cc, i32 %a, i32 %b, i32 %c, ptr 
%p) {
+; CHECK-LABEL: @no_reorder_atomic(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP0:%.*]] = load atomic volatile i32, ptr [[P:%.*]] 
acquire, align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = add nsw i32 [[C:%.*]], [[TMP1]]
+; CHECK-NEXT:    [[TMP3:%.*]] = mul nsw i32 [[TMP0]], [[TMP2]]
+; CHECK-NEXT:    br label [[IF_END:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[TMP4:%.*]] = load atomic volatile i32, ptr [[P]] acquire, 
align 4
+; CHECK-NEXT:    [[TMP5:%.*]] = sdiv i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP6:%.*]] = add nsw i32 [[C]], [[TMP5]]
+; CHECK-NEXT:    [[TMP7:%.*]] = mul nsw i32 [[TMP4]], [[TMP6]]
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[TMP3]], [[IF_THEN]] ], [ [[TMP7]], 
[[IF_ELSE]] ]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+entry:
+  br i1 %cc, label %if.then, label %if.else
+
+if.then:
+  %0 = load atomic volatile i32, ptr %p acquire, align 4
+  %1 = sdiv i32 %a, %b
+  %2 = add nsw i32 %c, %1
+  %3 = mul nsw i32 %0, %2
+  br label %if.end
+
+if.else:
+  %4 = load atomic volatile i32, ptr %p acquire, align 4
+  %5 = sdiv i32 %a, %b
+  %6 = add nsw i32 %c, %5
+  %7 = mul nsw i32 %4, %6
+  br label %if.end
+
+if.end:
+  %r = phi i32 [%3, %if.then], [%7, %if.else]
+  ret i32 %r
+}
+
+define dso_local i32 @multiple_use(i1 %cc, i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @multiple_use(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = mul nsw i32 [[TMP0]], [[C:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    br label [[IF_END:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP4:%.*]] = mul nsw i32 [[TMP3]], [[C]]
+; 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 = add nsw i32 %a, %b
+  %1 = mul nsw i32 %0, %c
+  %2 = add nsw i32 %0, %1
+  br label %if.end
+
+if.else:
+  %3 = add nsw i32 %a, %b
+  %4 = mul nsw i32 %3, %c
+  %5 = add nsw i32 %3, %4
+  br label %if.end
+
+if.end:
+  %r = phi i32 [%2, %if.then], [%5, %if.else]
+  ret i32 %r
+}
+
+; Different operand order in commutative operations
+define dso_local i32 @commutative_ops(i1 %cc, i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @commutative_ops(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add nsw i32 [[TMP0]], [[C:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = sdiv i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    br label [[IF_END:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i32 [[A]], [[B]]
+; CHECK-NEXT:    [[TMP4:%.*]] = add nsw i32 [[C]], [[TMP3]]
+; CHECK-NEXT:    [[TMP5:%.*]] = sdiv 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 = add nsw i32 %a, %b
+  %1 = add nsw i32 %0, %c
+  %2 = sdiv i32 %0, %1
+  br label %if.end
+
+if.else:
+  %3 = add nsw i32 %a, %b
+  %4 = add nsw i32 %c, %3
+  %5 = sdiv 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_hoist_mem(i1 %cc, ptr %p) {
+; CHECK-LABEL: @no_hoist_mem(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[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, ptr [[P]], align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i32 [[TMP2]], 1
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[TMP1]], [[IF_THEN]] ], [ [[TMP3]], 
[[IF_ELSE]] ]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+entry:
+  br i1 %cc, label %if.then, label %if.else
+
+if.then:
+  %0 = load i32, ptr %p
+  %1 = add nsw i32 %0, 1
+  br label %if.end
+
+if.else:
+  %2 = load i32, ptr %p
+  %3 = add nsw i32 %2, 1
+  br label %if.end
+
+if.end:
+  %r = phi i32 [%1, %if.then], [%3, %if.else]
+  ret i32 %r
+}
+
+define dso_local i32 @no_hoist_musttail(i1 %cc, i32 %x, ptr %p) {
+; CHECK-LABEL: @no_hoist_musttail(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P:%.*]], align 4
+; CHECK-NEXT:    [[W:%.*]] = add i32 [[V]], [[X:%.*]]
+; CHECK-NEXT:    br i1 [[CC:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK:       if.then:
+; CHECK-NEXT:    [[TMP0:%.*]] = musttail call i32 @will_return(i1 true, i32 
[[W]], ptr [[P]])
+; CHECK-NEXT:    ret i32 [[TMP0]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[TMP1:%.*]] = musttail call i32 @will_return(i1 false, i32 
[[W]], ptr [[P]])
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+entry:
+  %v = load i32, ptr %p
+  %w = add i32 %v, %x
+  br i1 %cc, label %if.then, label %if.else
+
+if.then:
+  %0 = musttail call i32 @will_return(i1 %cc, i32 %w, ptr %p)
+  ret i32 %0
+
+if.else:
+  %1 = musttail call i32 @will_return(i1 %cc, i32 %w, ptr %p)
+  ret i32 %1
+}
+
+declare i32 @barrier(i32) memory(none)
+declare void @will_return() nounwind willreturn

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to