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
