[llvm-branch-commits] [flang] [Flang][OpenMP] Remove the DeleteUnreachableTargets pass (PR #214183)
Sergio Afonso via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Aug 10 06:35:40 PDT 2026
https://github.com/skatrak updated https://github.com/llvm/llvm-project/pull/214183
>From c008226020ee05307108218eb29042e222a7bdfa Mon Sep 17 00:00:00 2001
From: Sergio Afonso <Sergio.AfonsoFumero at amd.com>
Date: Tue, 4 Aug 2026 11:04:00 +0100
Subject: [PATCH 1/2] [Flang][OpenMP] Remove the DeleteUnreachableTargets pass
The `DeleteUnreachableTargets` pass was initially added to work around
a problem caused by the interaction between the function filtering and
host op filtering passes and generic MLIR optimizations.
Specifically, by running function and host op filtering before these
optimizations, we would lose the ability to detect unreachable
`omp.target` operations when compiling for the device. This would cause
GPU kernels being created for them, for which no host counterpart
existed.
By now having moved both passes towards the end of the compilation
pipeline, after FIR to LLVM lowering, removal of unreachable host and
device code is no longer impacted by them. This makes the
`DeleteUnreachableTargets` pass redundant.
---
.../include/flang/Optimizer/OpenMP/Passes.td | 12 -
flang/lib/Optimizer/OpenMP/CMakeLists.txt | 1 -
.../OpenMP/DeleteUnreachableTargets.cpp | 76 -----
flang/lib/Optimizer/Passes/Pipelines.cpp | 3 -
flang/test/Lower/OpenMP/target-dead-code.f90 | 229 +++++++++++--
.../OpenMP/delete-unreachable-targets.mlir | 322 ------------------
6 files changed, 202 insertions(+), 441 deletions(-)
delete mode 100644 flang/lib/Optimizer/OpenMP/DeleteUnreachableTargets.cpp
delete mode 100644 flang/test/Transforms/OpenMP/delete-unreachable-targets.mlir
diff --git a/flang/include/flang/Optimizer/OpenMP/Passes.td b/flang/include/flang/Optimizer/OpenMP/Passes.td
index b81ff842948c3..08272d24252ee 100644
--- a/flang/include/flang/Optimizer/OpenMP/Passes.td
+++ b/flang/include/flang/Optimizer/OpenMP/Passes.td
@@ -35,18 +35,6 @@ def MapsForPrivatizedSymbolsPass
let dependentDialects = ["mlir::omp::OpenMPDialect"];
}
-def DeleteUnreachableTargetsPass
- : Pass<"omp-delete-unreachable-targets", "mlir::ModuleOp"> {
- let summary = "Deletes OpenMP target operations in unreachable code";
- let description = [{
- Identifies and removes OpenMP target operations that reside in unreachable
- code (e.g., inside if(.false.) blocks). This ensures consistency between
- host and device compilation by preventing unreachable targets from being
- processed on the device side.
- }];
- let dependentDialects = ["mlir::omp::OpenMPDialect"];
-}
-
def DoConcurrentConversionPass : Pass<"omp-do-concurrent-conversion", "mlir::ModuleOp"> {
let summary = "Map `DO CONCURRENT` loops to OpenMP worksharing loops.";
diff --git a/flang/lib/Optimizer/OpenMP/CMakeLists.txt b/flang/lib/Optimizer/OpenMP/CMakeLists.txt
index 9c14716f4f06a..f29ba86a8a28c 100644
--- a/flang/lib/Optimizer/OpenMP/CMakeLists.txt
+++ b/flang/lib/Optimizer/OpenMP/CMakeLists.txt
@@ -6,7 +6,6 @@ add_flang_library(FlangOpenMPTransforms
GenericLoopConversion.cpp
MapsForPrivatizedSymbols.cpp
MapInfoFinalization.cpp
- DeleteUnreachableTargets.cpp
LowerWorkdistribute.cpp
LowerWorkshare.cpp
LowerNontemporal.cpp
diff --git a/flang/lib/Optimizer/OpenMP/DeleteUnreachableTargets.cpp b/flang/lib/Optimizer/OpenMP/DeleteUnreachableTargets.cpp
deleted file mode 100644
index de2b226f85f23..0000000000000
--- a/flang/lib/Optimizer/OpenMP/DeleteUnreachableTargets.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-//===- DeleteUnreachableTargets.cpp --------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This pass removes OpenMP target operations that are in unreachable code.
-// This ensures host and device compilation have consistent target regions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "flang/Optimizer/OpenMP/Passes.h"
-#include "mlir/Analysis/DataFlow/DeadCodeAnalysis.h"
-#include "mlir/Analysis/DataFlow/Utils.h"
-#include "mlir/Analysis/DataFlowFramework.h"
-#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
-#include "mlir/IR/BuiltinOps.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Support/LLVM.h"
-#include "llvm/ADT/SmallVector.h"
-
-namespace flangomp {
-#define GEN_PASS_DEF_DELETEUNREACHABLETARGETSPASS
-#include "flang/Optimizer/OpenMP/Passes.h.inc"
-} // namespace flangomp
-
-using namespace mlir;
-
-namespace {
-
-/// Check if an operation is unreachable using DeadCodeAnalysis.
-static bool isOperationUnreachable(Operation *op, DataFlowSolver &solver) {
- Block *block = op->getBlock();
- if (!block)
- return false;
-
- // Query DeadCodeAnalysis to check if the block is live (reachable).
- ProgramPoint *point = solver.getProgramPointBefore(block);
- const dataflow::Executable *executable =
- solver.lookupState<dataflow::Executable>(point);
-
- return (executable && !executable->isLive());
-}
-
-class DeleteUnreachableTargetsPass
- : public flangomp::impl::DeleteUnreachableTargetsPassBase<
- DeleteUnreachableTargetsPass> {
-public:
- DeleteUnreachableTargetsPass() = default;
-
- void runOnOperation() override {
- auto module = getOperation();
- DataFlowSolver solver;
- dataflow::loadBaselineAnalyses(solver);
-
- if (failed(solver.initializeAndRun(module))) {
- signalPassFailure();
- return;
- }
-
- // Collect unreachable target operations
- SmallVector<omp::TargetOp> unreachableTargets;
- module.walk([&](omp::TargetOp targetOp) {
- if (isOperationUnreachable(targetOp.getOperation(), solver))
- unreachableTargets.push_back(targetOp);
- });
-
- // Delete unreachable target operations
- for (omp::TargetOp targetOp : unreachableTargets)
- targetOp->erase();
- }
-};
-
-} // namespace
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 2812d23bbec73..cc61237760178 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -372,9 +372,6 @@ void createOpenMPFIRPassPipeline(mlir::PassManager &pm,
pm.addPass(flangomp::createAutomapToTargetDataPass());
pm.addPass(flangomp::createMapInfoFinalizationPass());
- // Delete unreachable target operations before FunctionFilteringPass
- // extracts them.
- pm.addPass(flangomp::createDeleteUnreachableTargetsPass());
pm.addPass(flangomp::createGenericLoopConversionPass());
}
diff --git a/flang/test/Lower/OpenMP/target-dead-code.f90 b/flang/test/Lower/OpenMP/target-dead-code.f90
index 876618d6d963c..1e668cf78ce54 100644
--- a/flang/test/Lower/OpenMP/target-dead-code.f90
+++ b/flang/test/Lower/OpenMP/target-dead-code.f90
@@ -1,12 +1,14 @@
-! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s --check-prefix=FIR
+! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | tco -test-gen | FileCheck %s --check-prefixes=HOST,ALL
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | tco -test-gen | FileCheck %s --check-prefixes=DEVICE,ALL
-! Test that OpenMP target regions in dead code are deleted
+! Test that OpenMP target regions in dead code are deleted from both host and
+! target device.
! Test 1: if (.false.) with target - target should be deleted
-! FIR-LABEL: func.func @_QPtest_dead_simple
-! FIR: %[[FALSE:.*]] = arith.constant false
-! FIR: fir.if %[[FALSE]] {
-! FIR-NOT: omp.target
+! HOST-LABEL: llvm.func @_QPtest_dead_simple
+! HOST-NOT: omp.target
+! HOST: llvm.return
+! DEVICE-NOT: llvm.func @_QPtest_dead_simple
subroutine test_dead_simple()
real :: v
if (.false.) then
@@ -17,39 +19,49 @@ subroutine test_dead_simple()
end subroutine
! Test 2: Live target - should remain
-! FIR-LABEL: func.func @_QPtest_live_simple
-! FIR: omp.target
+! ALL-LABEL: llvm.func @_QPtest_live_simple
+! ALL: omp.target
+! ALL: llvm.return
subroutine test_live_simple()
real :: v
- !$omp target map(tofrom:v)
- v = 2.0
- !$omp end target
+ if (.true.) then
+ !$omp target map(tofrom:v)
+ v = 2.0
+ !$omp end target
+ end if
end subroutine
! Test 3: Mixed dead and live
-! FIR-LABEL: func.func @_QPtest_mixed
+! ALL-LABEL: llvm.func @_QPtest_mixed
subroutine test_mixed()
real :: v
! Dead - should be deleted
- ! FIR: fir.if %{{.*}} {
+ ! ALL-NOT: {{.*}} = llvm.mlir.constant(3.0{{.*}} : f32)
if (.false.) then
!$omp target map(tofrom:v)
v = 3.0
!$omp end target
end if
- ! FIR-NOT: omp.target
- ! Live - should remain (expect exactly 1 omp.target in function)
+
+ ! Live - should remain
!$omp target map(tofrom:v)
- ! FIR: omp.target
+ ! ALL: omp.target
+ ! ALL: {{.*}} = llvm.mlir.constant(4.0{{.*}} : f32)
v = 4.0
!$omp end target
+
+ ! Expect exactly 1 omp.target in function
+ ! ALL-NOT: omp.target
+ ! ALL: llvm.return
end subroutine
! Test 4: Nested - outer false, target should be deleted
-! FIR-LABEL: func.func @_QPtest_nested_outer_false
+! HOST-LABEL: llvm.func @_QPtest_nested_outer_false
+! HOST-NOT: omp.target
+! HOST: llvm.return
+! DEVICE-NOT: llvm.func @_QPtest_nested_outer_false
subroutine test_nested_outer_false()
real :: v
- ! FIR: fir.if %{{.*}} {
if (.false.) then
if (.true.) then
!$omp target map(tofrom:v)
@@ -57,32 +69,195 @@ subroutine test_nested_outer_false()
!$omp end target
end if
end if
- ! FIR-NOT: omp.target
end subroutine
-! Test 5: Parameter constant - target should be deleted
-! FIR-LABEL: func.func @_QPtest_parameter
+! Test 5: Nested - inner false, target should be deleted
+! HOST-LABEL: llvm.func @_QPtest_nested_inner_false
+! HOST-NOT: omp.target
+! HOST: llvm.return
+! DEVICE-NOT: llvm.func @_QPtest_nested_inner_false
+subroutine test_nested_inner_false()
+ real :: v
+ if (.true.) then
+ if (.false.) then
+ !$omp target map(tofrom:v)
+ v = 6.0
+ !$omp end target
+ end if
+ end if
+end subroutine
+
+! Test 6: Nested - both true, target should remain
+! ALL-LABEL: llvm.func @_QPtest_nested_both_true
+! ALL: omp.target
+! ALL: llvm.return
+subroutine test_nested_both_true()
+ real :: v
+ if (.true.) then
+ if (.true.) then
+ !$omp target map(tofrom:v)
+ v = 7.0
+ !$omp end target
+ end if
+ end if
+end subroutine
+
+! Test 7: Multiple dead targets in dead branch - all should be deleted
+! HOST-LABEL: llvm.func @_QPtest_multiple_dead_targets
+! HOST-NOT: omp.target
+! HOST: llvm.return
+! DEVICE-NOT: llvm.func @_QPtest_multiple_dead_targets
+subroutine test_multiple_dead_targets()
+ real :: v
+ if (.false.) then
+ !$omp target map(tofrom:v)
+ v = 8.0
+ !$omp end target
+ !$omp target map(tofrom:v)
+ v = 9.0
+ !$omp end target
+ !$omp target map(tofrom:v)
+ v = 10.0
+ !$omp end target
+ end if
+end subroutine
+
+! Test 8: Parameter constant - target should be deleted
+! HOST-LABEL: llvm.func @_QPtest_parameter
+! HOST-NOT: omp.target
+! HOST: llvm.return
+! DEVICE-NOT: llvm.func @_QPtest_parameter
subroutine test_parameter()
real :: v
logical, parameter :: DEAD = .false.
- ! FIR: fir.if %{{.*}} {
if (DEAD) then
!$omp target map(tofrom:v)
- v = 6.0
+ v = 11.0
!$omp end target
end if
- ! FIR-NOT: omp.target
end subroutine
-! FIR-LABEL: func.func @_QPtest_outer
+! Test 9: Unused nested subroutine - target should be deleted
+! HOST-LABEL: llvm.func @_QPtest_outer
+! HOST-NOT: omp.target
+! HOST: llvm.return
+! DEVICE-NOT: llvm.func @_QPtest_outer
subroutine test_outer
implicit none
contains
subroutine unused_sub()
real :: v
!$omp target map(tofrom: v)
- v = 5.0
+ v = 12.0
!$omp end target
end subroutine
- ! FIR-NOT: omp.target
+end subroutine
+
+! Test 10: if (.false.) with else - then-branch target deleted, else-branch remains
+! ALL-LABEL: llvm.func @_QPtest_if_else_false
+subroutine test_if_else_false()
+ real :: v
+ ! Dead then-branch - target should be deleted
+ ! ALL-NOT: {{.*}} = llvm.mlir.constant(1.3{{.*}}e+01 : f32)
+ if (.false.) then
+ !$omp target map(tofrom:v)
+ v = 13.0
+ !$omp end target
+ else
+ ! Live else-branch - target should remain
+ !$omp target map(tofrom:v)
+ ! ALL: omp.target
+ ! ALL: {{.*}} = llvm.mlir.constant(1.4{{.*}}e+01 : f32)
+ v = 14.0
+ !$omp end target
+ end if
+ ! Expect exactly 1 omp.target in function
+ ! ALL-NOT: omp.target
+ ! ALL: llvm.return
+end subroutine
+
+! Test 11: Runtime condition - target should remain unchanged
+! ALL-LABEL: llvm.func @_QPtest_runtime_condition
+! ALL: omp.target
+! ALL: llvm.return
+subroutine test_runtime_condition(cond)
+ logical, intent(in) :: cond
+ real :: v
+ if (cond) then
+ !$omp target map(tofrom:v)
+ v = 15.0
+ !$omp end target
+ end if
+end subroutine
+
+! Test 12: Target nested in unreachable block - target should be deleted
+! ALL-LABEL: llvm.func @_QPtest_nested_in_unreachable_block
+subroutine test_nested_in_unreachable_block()
+ real :: v
+ go to 10
+ ! Unreachable block: even though condition is .true., the block itself is dead
+ ! ALL-NOT: {{.*}} = llvm.mlir.constant(1.6{{.*}}e+01 : f32)
+ if (.true.) then
+ !$omp target map(tofrom:v)
+ v = 16.0
+ !$omp end target
+ end if
+10 continue
+ ! Reachable - target should remain
+ !$omp target map(tofrom:v)
+ ! ALL: omp.target
+ ! ALL: {{.*}} = llvm.mlir.constant(1.7{{.*}}e+01 : f32)
+ v = 17.0
+ !$omp end target
+ ! Expect exactly 1 omp.target in function
+ ! ALL-NOT: omp.target
+ ! ALL: llvm.return
+end subroutine
+
+! Test 13: Multiple targets in unreachable blocks - all should be deleted
+! ALL-LABEL: llvm.func @_QPtest_multiple_unreachable_blocks
+subroutine test_multiple_unreachable_blocks()
+ real :: v
+ go to 30
+ ! First unreachable block - target should be deleted
+ ! ALL-NOT: {{.*}} = llvm.mlir.constant(1.8{{.*}}e+01 : f32)
+ !$omp target map(tofrom:v)
+ v = 18.0
+ !$omp end target
+ go to 20
+20 continue
+ ! Second unreachable block (only reachable from first unreachable block)
+ ! ALL-NOT: {{.*}} = llvm.mlir.constant(1.9{{.*}}e+01 : f32)
+ !$omp target map(tofrom:v)
+ v = 19.0
+ !$omp end target
+30 continue
+ ! Reachable from entry - target should remain
+ !$omp target map(tofrom:v)
+ ! ALL: omp.target
+ ! ALL: {{.*}} = llvm.mlir.constant(2.0{{.*}}e+01 : f32)
+ v = 20.0
+ !$omp end target
+ ! Expect exactly 1 omp.target in function
+ ! ALL-NOT: omp.target
+ ! ALL: llvm.return
+end subroutine
+
+! Test 14: Both branches reachable - all targets should remain
+! ALL-LABEL: llvm.func @_QPtest_both_branches_reachable
+! ALL: omp.target
+! ALL: omp.target
+! ALL: llvm.return
+subroutine test_both_branches_reachable(cond)
+ logical, intent(in) :: cond
+ real :: v
+ if (cond) then
+ !$omp target map(tofrom:v)
+ v = 21.0
+ !$omp end target
+ else
+ !$omp target map(tofrom:v)
+ v = 22.0
+ !$omp end target
+ end if
end subroutine
diff --git a/flang/test/Transforms/OpenMP/delete-unreachable-targets.mlir b/flang/test/Transforms/OpenMP/delete-unreachable-targets.mlir
deleted file mode 100644
index 6db167b51039d..0000000000000
--- a/flang/test/Transforms/OpenMP/delete-unreachable-targets.mlir
+++ /dev/null
@@ -1,322 +0,0 @@
-// RUN: fir-opt --omp-delete-unreachable-targets %s | FileCheck %s
-
-// This test verifies that OpenMP target operations in unreachable code are
-// deleted.
-
-
-// CHECK-LABEL: func.func @test_if_false_simple
-func.func @test_if_false_simple() {
- %false = arith.constant false
- // The target in the dead branch should be removed
- // CHECK: fir.if %false {
- // CHECK-NOT: omp.target
- // CHECK: }
- fir.if %false {
- omp.target kernel_type(generic) {
- omp.terminator
- }
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_if_true_simple
-func.func @test_if_true_simple() {
- %true = arith.constant true
- // The target should remain since the branch is reachable
- // CHECK: omp.target
- fir.if %true {
- omp.target kernel_type(generic) {
- omp.terminator
- }
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_nested_outer_false
-func.func @test_nested_outer_false() {
- %false = arith.constant false
- %true = arith.constant true
- // Outer false makes the whole nested structure unreachable
- // CHECK: fir.if %false {
- // CHECK-NOT: omp.target
- // CHECK: }
- fir.if %false {
- fir.if %true {
- omp.target kernel_type(generic) {
- omp.terminator
- }
- }
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_nested_inner_false
-func.func @test_nested_inner_false() {
- %false = arith.constant false
- %true = arith.constant true
- // Outer true, inner false - target should be removed
- // CHECK: fir.if %true {
- // CHECK: fir.if %false {
- // CHECK-NOT: omp.target
- // CHECK: }
- fir.if %true {
- fir.if %false {
- omp.target kernel_type(generic) {
- omp.terminator
- }
- }
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_nested_both_true
-func.func @test_nested_both_true() {
- %true1 = arith.constant true
- %true2 = arith.constant true
- // CHECK: omp.target
- fir.if %true1 {
- fir.if %true2 {
- omp.target kernel_type(generic) {
- omp.terminator
- }
- }
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_mixed_targets
-func.func @test_mixed_targets() {
- %false = arith.constant false
- %true = arith.constant true
-
- // Live target - should remain (expect 2 targets total in output)
- // CHECK: omp.target
- omp.target kernel_type(generic) {
- omp.terminator
- }
-
- // Another live target in if (true) - should remain
- // CHECK: omp.target
- fir.if %true {
- omp.target kernel_type(generic) {
- omp.terminator
- }
- }
-
- // Dead target - will be removed
- // CHECK-NOT: omp.target
- fir.if %false {
- omp.target kernel_type(generic) {
- omp.terminator
- }
- }
-
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_multiple_dead_targets
-func.func @test_multiple_dead_targets() {
- %false = arith.constant false
-
- // All targets inside dead branch should be removed
- // CHECK-NOT: omp.target
- fir.if %false {
- omp.target kernel_type(generic) {
- omp.terminator
- }
-
- omp.target kernel_type(generic) {
- omp.terminator
- }
-
- omp.target kernel_type(generic) {
- omp.terminator
- }
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_if_else_false
-func.func @test_if_else_false() {
- %false = arith.constant false
-
- // CHECK: fir.if %false {
- fir.if %false {
- // Then branch is unreachable, target should be deleted
- omp.target kernel_type(generic) {
- omp.terminator
- }
- } else {
- // CHECK-NOT: omp.target
- // CHECK: } else {
- // Else branch is reachable, target should remain
- // CHECK: omp.target
- omp.target kernel_type(generic) {
- omp.terminator
- }
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_runtime_condition
-func.func @test_runtime_condition(%arg0: i1) {
- // Runtime condition - cannot be optimized, should remain unchanged
- // CHECK: fir.if %arg0 {
- fir.if %arg0 {
- // CHECK: omp.target
- omp.target kernel_type(generic) {
- omp.terminator
- }
- }
- return
-}
-
-// -----
-
-// Test that targets nested in structured control flow within unreachable blocks
-// are correctly identified as unreachable
-// CHECK-LABEL: func.func @test_nested_in_unreachable_block
-func.func @test_nested_in_unreachable_block() {
- cf.br ^bb2
-^bb1:
- // This entire block is unreachable
- // Even though the fir.if condition is true, the whole block is dead
- %true = arith.constant true
- // CHECK: ^bb1:
- // CHECK-NOT: omp.target
- // CHECK: cf.br ^bb2
- fir.if %true {
- omp.target kernel_type(generic) {
- omp.terminator
- }
- }
- cf.br ^bb2
-^bb2:
- // CHECK: ^bb2:
- // CHECK-NEXT: omp.target
- omp.target kernel_type(generic) {
- omp.terminator
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_unreachable_block_after_branch
-func.func @test_unreachable_block_after_branch() {
- cf.br ^bb2
-^bb1:
- // This block is unreachable - no predecessor branches to it
- // CHECK: ^bb1:
- // CHECK-NOT: omp.target
- // CHECK: cf.br ^bb2
- omp.target kernel_type(generic) {
- omp.terminator
- }
- cf.br ^bb2
-^bb2:
- // This block is reachable
- // CHECK: ^bb2:
- // CHECK-NEXT: omp.target
- omp.target kernel_type(generic) {
- omp.terminator
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_multiple_unreachable_blocks
-func.func @test_multiple_unreachable_blocks() {
- cf.br ^bb3
-^bb1:
- // Unreachable block - no predecessor branches to it
- // CHECK: ^bb1:
- // CHECK-NOT: omp.target
- // CHECK: cf.br ^bb2
- omp.target kernel_type(generic) {
- omp.terminator
- }
- cf.br ^bb2
-^bb2:
- // Also unreachable - only reachable from ^bb1 which is itself unreachable
- // CHECK: ^bb2:
- // CHECK-NOT: omp.target
- // CHECK: return
- omp.target kernel_type(generic) {
- omp.terminator
- }
- return
-^bb3:
- // Reachable from entry
- // CHECK: ^bb3:
- // CHECK-NEXT: omp.target
- omp.target kernel_type(generic) {
- omp.terminator
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_both_branches_reachable
-func.func @test_both_branches_reachable(%arg0: i1) {
- cf.cond_br %arg0, ^bb1, ^bb2
-^bb1:
- // CHECK: ^bb1:
- // CHECK-NEXT: omp.target
- omp.target kernel_type(generic) {
- omp.terminator
- }
- cf.br ^bb3
-^bb2:
- // CHECK: ^bb2:
- // CHECK-NEXT: omp.target
- omp.target kernel_type(generic) {
- omp.terminator
- }
- cf.br ^bb3
-^bb3:
- return
-}
-
-// -----
-
-// CHECK-LABEL: func.func @test_disconnected_block
-func.func @test_disconnected_block() {
- // Entry goes directly to exit
- cf.br ^bb2
-^bb1:
- // This block is completely disconnected - no way to reach it
- // CHECK: ^bb1:
- // CHECK-NOT: omp.target
- // CHECK: cf.br ^bb2
- omp.target kernel_type(generic) {
- omp.terminator
- }
- cf.br ^bb2
-^bb2:
- // Reachable from entry
- // CHECK: ^bb2:
- // CHECK-NEXT: omp.target
- omp.target kernel_type(generic) {
- omp.terminator
- }
- return
-}
>From aa8e49327ea77afcfca2a8e1da4776c914ef22ad Mon Sep 17 00:00:00 2001
From: Sergio Afonso <Sergio.AfonsoFumero at amd.com>
Date: Mon, 10 Aug 2026 13:31:26 +0100
Subject: [PATCH 2/2] Address review comments
---
.../{Lower => Integration}/OpenMP/target-dead-code.f90 | 8 ++++++++
1 file changed, 8 insertions(+)
rename flang/test/{Lower => Integration}/OpenMP/target-dead-code.f90 (93%)
diff --git a/flang/test/Lower/OpenMP/target-dead-code.f90 b/flang/test/Integration/OpenMP/target-dead-code.f90
similarity index 93%
rename from flang/test/Lower/OpenMP/target-dead-code.f90
rename to flang/test/Integration/OpenMP/target-dead-code.f90
index 1e668cf78ce54..cdcf7d39bb67c 100644
--- a/flang/test/Lower/OpenMP/target-dead-code.f90
+++ b/flang/test/Integration/OpenMP/target-dead-code.f90
@@ -1,3 +1,11 @@
+!===----------------------------------------------------------------------===!
+! This directory can be used to add Integration tests involving multiple
+! stages of the compiler (for eg. from Fortran to LLVM IR). It should not
+! contain executable tests. We should only add tests here sparingly and only
+! if there is no other way to test. Repeat this message in each test that is
+! added to this directory and sub-directories.
+!===----------------------------------------------------------------------===!
+
! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | tco -test-gen | FileCheck %s --check-prefixes=HOST,ALL
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | tco -test-gen | FileCheck %s --check-prefixes=DEVICE,ALL
More information about the llvm-branch-commits
mailing list