[clang] [Clang] Enable -fextend-lifetimes at -Og (PR #118026)

Stephen Tozer via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 28 09:24:01 PST 2024


https://github.com/SLTozer created https://github.com/llvm/llvm-project/pull/118026

This patch follows two other ongoing reviews, https://github.com/llvm/llvm-project/pull/110000 and https://github.com/llvm/llvm-project/pull/110102, which add a new feature to Clang - `-fextend-lifetimes`, which generates fake uses for user variables (and the `this` pointer) to prevent them from being optimized out, providing a better debug experience at the cost of less efficient generated code. This is useful for debugging code without the need to disable optimizations outright, which is particularly important when debugging applications where some level of optimization is necessary, e.g. game code.

Following the inclusion of the flag, this patch enables it by default when `-Og` is set. Currently, `-Og` is equivalent to `-O1` - it is effectively just an alias. By enabling `-fextend-lifetimes`, this patch changes the code generated by Clang with `-Og` to have reduced optimization and greater debuggability than `-O1`, differentiating the two according to their respective purposes. This idea was discussed previously on [Discourse](https://discourse.llvm.org/t/rfc-redefine-og-o1-and-add-a-new-level-of-og/72850), where there was general agreement with the principle of this change.

>From 7e42a82d73e3be98aab8e523b16a2e43d31b0552 Mon Sep 17 00:00:00 2001
From: Stephen Tozer <stephen.tozer at sony.com>
Date: Thu, 28 Nov 2024 13:53:20 +0000
Subject: [PATCH] Enable -fextend-lifetimes at -Og

---
 clang/docs/CommandGuide/clang.rst         |  7 ++++--
 clang/docs/ReleaseNotes.rst               |  4 +++
 clang/lib/Frontend/CompilerInvocation.cpp |  8 ++++++
 clang/test/CodeGen/fake-use-opt-flags.cpp | 30 +++++++++++++++++++++++
 4 files changed, 47 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGen/fake-use-opt-flags.cpp

diff --git a/clang/docs/CommandGuide/clang.rst b/clang/docs/CommandGuide/clang.rst
index ca8176f854729b..8f3f0de9446b41 100644
--- a/clang/docs/CommandGuide/clang.rst
+++ b/clang/docs/CommandGuide/clang.rst
@@ -442,8 +442,11 @@ Code Generation Options
     :option:`-Oz` Like :option:`-Os` (and thus :option:`-O2`), but reduces code
     size further.
 
-    :option:`-Og` Like :option:`-O1`. In future versions, this option might
-    disable different optimizations in order to improve debuggability.
+    :option:`-Og` Similar to :option:`-O1`, but with slightly reduced
+    optimization and better variable visibility. The same optimizations are run
+    as at :option:`-O1`, but the :option:`-fextend-lifetimes` flag is also
+    set, which tries to prevent optimizations from reducing the lifetime of
+    user variables.
 
     :option:`-O` Equivalent to :option:`-O1`.
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 601a233b81904f..14fec70dfb85f7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -441,6 +441,10 @@ Modified Compiler Flags
   ``memset`` and similar functions for which it is a documented undefined
   behavior. It is implied by ``-Wnontrivial-memaccess``
 
+- The ``-Og`` optimization flag now sets ``-fextend-lifetimes``, a new compiler
+  flag, resulting in slightly reduced optimization compared to ``-O1`` in
+  exchange for improved variable visibility.
+
 Removed Compiler Flags
 -------------------------
 
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 3dd94c31b2bc7a..09322d0617aaad 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1834,6 +1834,14 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
     Opts.setInlining(CodeGenOptions::NormalInlining);
   }
 
+  // If we have specified -Og and have not set any explicit -fextend-lifetimes
+  // value, then default to -fextend-lifetimes=all.
+  if (Arg *A = Args.getLastArg(options::OPT_O_Group);
+      A && A->containsValue("g")) {
+    if (!Args.hasArg(options::OPT_fextend_lifetimes))
+      Opts.ExtendLifetimes = true;
+  }
+
   // PIC defaults to -fno-direct-access-external-data while non-PIC defaults to
   // -fdirect-access-external-data.
   Opts.DirectAccessExternalData =
diff --git a/clang/test/CodeGen/fake-use-opt-flags.cpp b/clang/test/CodeGen/fake-use-opt-flags.cpp
new file mode 100644
index 00000000000000..a99ed7a573ab22
--- /dev/null
+++ b/clang/test/CodeGen/fake-use-opt-flags.cpp
@@ -0,0 +1,30 @@
+/// Check that we generate fake uses only when -fextend-lifetimes is set and we
+/// are not setting optnone, or when we have optimizations set to -Og and we have
+/// not passed -fno-extend-lifetimes.
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -O0 -fextend-lifetimes %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -O0 -disable-O0-optnone -fextend-lifetimes %s -o - | FileCheck %s --check-prefixes=CHECK,EXTEND
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -Og %s -o - | FileCheck %s --check-prefixes=CHECK,EXTEND
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -Og -fno-extend-lifetimes %s -o - | FileCheck %s
+
+/// Test various optimization flags with -fextend-lifetimes...
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -O1 %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -O1 -fextend-lifetimes %s -o - | FileCheck %s --check-prefixes=CHECK,EXTEND
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -O2 %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -O2 -fextend-lifetimes %s -o - | FileCheck %s --check-prefixes=CHECK,EXTEND
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -O3 %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -O3 -fextend-lifetimes %s -o - | FileCheck %s --check-prefixes=CHECK,EXTEND
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -Os %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -Os -fextend-lifetimes %s -o - | FileCheck %s --check-prefixes=CHECK,EXTEND
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -Oz %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -disable-llvm-passes -Oz -fextend-lifetimes %s -o - | FileCheck %s --check-prefixes=CHECK,EXTEND
+
+// CHECK-LABEL: define{{.*}} void @_Z3fooi(i32{{.*}} %a)
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    %a.addr = alloca i32
+// CHECK-NEXT:    store i32 %a, ptr %a.addr
+// EXTEND-NEXT:   %fake.use = load i32, ptr %a.addr
+// EXTEND-NEXT:   call void (...) @llvm.fake.use(i32 %fake.use)
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+void foo(int a) {}



More information about the cfe-commits mailing list