blob: ae22de199ce4b805e1c1877edd442bbd4bcc636b [file] [edit]
// RUN: fir-opt --split-input-file --pass-pipeline="builtin.module(cg-rewrite)" %s | FileCheck %s
// Test that the PreCGRewrite pass (cg-rewrite) materializes a cf.cond_br
// diamond around fircg.ext_rebox / fircg.ext_embox when the original
// fir.rebox / fir.embox carries the `optional` attribute.
// CHECK-LABEL: func.func @test_rebox_optional(
// CHECK-SAME: %[[BOX:.*]]: !fir.box<!fir.array<?xf32>>)
func.func @test_rebox_optional(%arg0: !fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>> {
%c0 = arith.constant 0 : index
%0 = fir.shift %c0 : (index) -> !fir.shift<1>
%1 = fir.rebox %arg0(%0) optional : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>) -> !fir.box<!fir.array<?xf32>>
return %1 : !fir.box<!fir.array<?xf32>>
}
// CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[BOX]] : (!fir.box<!fir.array<?xf32>>) -> i1
// CHECK: cf.cond_br %[[IS_PRESENT]], ^[[THEN:.*]], ^[[ELSE:.*]]
// CHECK: ^[[THEN]]:
// CHECK: %[[EXTREBOX:.*]] = fircg.ext_rebox %[[BOX]] origin %{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> !fir.box<!fir.array<?xf32>>
// CHECK: cf.br ^[[MERGE:.*]](%[[EXTREBOX]] : !fir.box<!fir.array<?xf32>>)
// CHECK: ^[[ELSE]]:
// CHECK: %[[ABSENT:.*]] = fir.absent !fir.box<!fir.array<?xf32>>
// CHECK: cf.br ^[[MERGE]](%[[ABSENT]] : !fir.box<!fir.array<?xf32>>)
// CHECK: ^[[MERGE]](%[[MERGED:.*]]: !fir.box<!fir.array<?xf32>>):
// CHECK: return %[[MERGED]] : !fir.box<!fir.array<?xf32>>
// -----
// CHECK-LABEL: func.func @test_embox_optional_dynamic(
// CHECK-SAME: %[[REF:.*]]: !fir.ref<!fir.array<?xi32>>)
func.func @test_embox_optional_dynamic(%arg0: !fir.ref<!fir.array<?xi32>>) -> !fir.box<!fir.array<?xi32>> {
%c10 = arith.constant 10 : index
%0 = fir.shape %c10 : (index) -> !fir.shape<1>
%1 = fir.embox %arg0(%0) optional : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<?xi32>>
return %1 : !fir.box<!fir.array<?xi32>>
}
// CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[REF]] : (!fir.ref<!fir.array<?xi32>>) -> i1
// CHECK: cf.cond_br %[[IS_PRESENT]], ^[[THEN:.*]], ^[[ELSE:.*]]
// CHECK: ^[[THEN]]:
// CHECK: %[[EXTEMBOX:.*]] = fircg.ext_embox %[[REF]](%{{.*}}) : (!fir.ref<!fir.array<?xi32>>, index) -> !fir.box<!fir.array<?xi32>>
// CHECK: cf.br ^[[MERGE:.*]](%[[EXTEMBOX]] : !fir.box<!fir.array<?xi32>>)
// CHECK: ^[[ELSE]]:
// CHECK: %[[ABSENT:.*]] = fir.absent !fir.box<!fir.array<?xi32>>
// CHECK: cf.br ^[[MERGE]](%[[ABSENT]] : !fir.box<!fir.array<?xi32>>)
// CHECK: ^[[MERGE]](%[[MERGED:.*]]: !fir.box<!fir.array<?xi32>>):
// CHECK: return %[[MERGED]] : !fir.box<!fir.array<?xi32>>
// -----
// CHECK-LABEL: func.func @test_embox_optional_static(
// CHECK-SAME: %[[REF:.*]]: !fir.ref<!fir.array<10xi32>>)
func.func @test_embox_optional_static(%arg0: !fir.ref<!fir.array<10xi32>>) -> !fir.box<!fir.array<10xi32>> {
%1 = fir.embox %arg0 optional : (!fir.ref<!fir.array<10xi32>>) -> !fir.box<!fir.array<10xi32>>
return %1 : !fir.box<!fir.array<10xi32>>
}
// CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[REF]] : (!fir.ref<!fir.array<10xi32>>) -> i1
// CHECK: cf.cond_br %[[IS_PRESENT]], ^[[THEN:.*]], ^[[ELSE:.*]]
// CHECK: ^[[THEN]]:
// CHECK: %[[EXTEMBOX:.*]] = fircg.ext_embox %[[REF]](%{{.*}}) : (!fir.ref<!fir.array<10xi32>>, index) -> !fir.box<!fir.array<10xi32>>
// CHECK: cf.br ^[[MERGE:.*]](%[[EXTEMBOX]] : !fir.box<!fir.array<10xi32>>)
// CHECK: ^[[ELSE]]:
// CHECK: %[[ABSENT:.*]] = fir.absent !fir.box<!fir.array<10xi32>>
// CHECK: cf.br ^[[MERGE]](%[[ABSENT]] : !fir.box<!fir.array<10xi32>>)
// CHECK: ^[[MERGE]](%[[MERGED:.*]]: !fir.box<!fir.array<10xi32>>):
// CHECK: return %[[MERGED]] : !fir.box<!fir.array<10xi32>>
// -----
// An embox that is "kept as is" by the pass (no shape, scalar element type)
// is also wrapped in a cf.cond_br guard. The cloned embox in the "present"
// branch has its `optional` attribute dropped so that LLVM codegen sees a
// plain fir.embox.
// CHECK-LABEL: func.func @test_embox_optional_scalar_keep(
// CHECK-SAME: %[[REF:.*]]: !fir.ref<i32>)
func.func @test_embox_optional_scalar_keep(%arg0: !fir.ref<i32>) -> !fir.box<i32> {
%0 = fir.embox %arg0 optional : (!fir.ref<i32>) -> !fir.box<i32>
return %0 : !fir.box<i32>
}
// CHECK: %[[IS_PRESENT:.*]] = fir.is_present %[[REF]] : (!fir.ref<i32>) -> i1
// CHECK: cf.cond_br %[[IS_PRESENT]], ^[[THEN:.*]], ^[[ELSE:.*]]
// CHECK: ^[[THEN]]:
// CHECK: %[[EMBOX:.*]] = fir.embox %[[REF]] : (!fir.ref<i32>) -> !fir.box<i32>
// CHECK-NOT: optional
// CHECK: cf.br ^[[MERGE:.*]](%[[EMBOX]] : !fir.box<i32>)
// CHECK: ^[[ELSE]]:
// CHECK: %[[ABSENT:.*]] = fir.absent !fir.box<i32>
// CHECK: cf.br ^[[MERGE]](%[[ABSENT]] : !fir.box<i32>)
// CHECK: ^[[MERGE]](%[[MERGED:.*]]: !fir.box<i32>):
// CHECK: return %[[MERGED]] : !fir.box<i32>