[flang-commits] [flang] [llvm] [flang] Enhance show_descriptor intrinsic to avoid extra copies and extra descriptor creation (PR #173461)

via flang-commits flang-commits at lists.llvm.org
Thu Jan 8 01:28:02 PST 2026


================
@@ -7893,9 +7893,29 @@ void IntrinsicLibrary::genShowDescriptor(
   assert(args.size() == 1 && "expected single argument for show_descriptor");
   const mlir::Value descriptor = fir::getBase(args[0]);
 
-  assert(fir::isa_box_type(descriptor.getType()) &&
-         "argument must have been lowered to box type");
-  fir::runtime::genShowDescriptor(builder, loc, descriptor);
+  // Use consistent !fir.ref<!fir.box<none>> argument type
+  auto targetType = fir::BoxType::get(builder.getNoneType());
+  auto targetRefType = fir::ReferenceType::get(targetType);
+
+  // If it's already a reference to a box, convert it to correct type and
+  // pass it directly
+  if (fir::isa_ref_type(descriptor.getType()) &&
+      fir::isa_box_type(fir::unwrapRefType(descriptor.getType()))) {
+    fir::runtime::genShowDescriptor(
+        builder, loc, builder.createConvert(loc, targetRefType, descriptor));
+    return;
+  }
+
+  mlir::Value descrAddr = nullptr;
+  if (fir::isa_box_type(descriptor.getType())) {
+    // Spill it to the stack
+    descrAddr = builder.createTemporary(loc, targetType);
+    builder.createStoreWithConvert(loc, descriptor, descrAddr);
+  } else {
+    // If argument is not a box type (and not ref<box>), pass fir.absent.
+    descrAddr = builder.genAbsentOp(loc, targetRefType);
----------------
jeanPerier wrote:

>  For example, if that arg is "actual descriptor", display the descriptor information like right now. "temporary descriptor" would mean that descriptor was not originally on the stack, so don't display descriptor's address, but display the address of the buffer wrapped in the descriptor. "not a descriptor" would not display descriptor metadata, but would only display information about entity/variable.

With flang codegen, all descriptors outside of POINTER/ALLOCATABLE are temporary in the sense that lowering freely generates new ones here and there and will remove them after optimizations when unused/scalarize them. Even for assumed shapes, the address of the descriptor that you will get with `show_descriptor` may not be the address of the descriptor that was passed in register during the call because a new one may have been created to account for local lower bounds.

> I think that the users who will want to call show_descriptor() will be advanced users and they will certainly want to know

It is fair point which led me to go back the original motivation of adding this function, and I think we may be getting side tracked by the descriptor aspect while the intent of `show_descriptor` was to provide an equivalent of `pgf90_show` that is more about printing information about entities than dealing with descriptor specifically.

If you test the following with classic flang/nvfortran, you will get output while these entities do not need descriptors in flang lowering/codegen:
```
 real :: x(10)
 call pgf90_show(x)
 call pgf90_show(x(1))
end
```

The equivalent function in flang was named `show_descriptor` for flang because it happen to print the descriptor that would create/or exists for this entity.

Maybe a possible outcome from this discussion would be to update the documentation of this function to clarify that the address of the descriptor is only relevant for POINTER/ALLOCATABLE and otherwise that the descriptor address may be the address of a temp that was specifically created for the `show_descriptor` and should not be used to identify the variable.

https://github.com/llvm/llvm-project/pull/173461


More information about the flang-commits mailing list