[libunwind] [IPSCCP] Variable not visible at Og. (PR #66745)

Carlos Alberto Enciso via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 6 00:26:33 PDT 2023


https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/66745

>From b24943f63025822a5c5ba90c4a7b47f7123ec4db Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <carlos.alberto.enciso at gmail.com>
Date: Mon, 18 Sep 2023 12:29:17 +0100
Subject: [PATCH 1/4] [IPSCCP] Variable not visible at Og:

https://bugs.llvm.org/show_bug.cgi?id=51559
https://github.com/llvm/llvm-project/issues/50901

IPSCCP pass removes the global variable and does not
create a constant expression for the initializer value.
---
 llvm/lib/Transforms/IPO/SCCP.cpp     |  47 +++++++
 llvm/test/Transforms/SCCP/pr50901.ll | 184 +++++++++++++++++++++++++++
 2 files changed, 231 insertions(+)
 create mode 100644 llvm/test/Transforms/SCCP/pr50901.ll

diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp
index 84f5bbf7039416b..e09769e00148143 100644
--- a/llvm/lib/Transforms/IPO/SCCP.cpp
+++ b/llvm/lib/Transforms/IPO/SCCP.cpp
@@ -22,6 +22,7 @@
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/AttributeMask.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ModRef.h"
@@ -371,6 +372,52 @@ static bool runIPSCCP(
       StoreInst *SI = cast<StoreInst>(GV->user_back());
       SI->eraseFromParent();
     }
+
+    // Try to create a debug constant expression for the glbal variable
+    // initializer value.
+    SmallVector<DIGlobalVariableExpression *, 1> GVEs;
+    GV->getDebugInfo(GVEs);
+    if (GVEs.size() == 1) {
+      DIBuilder DIB(M);
+
+      // Create integer constant expression.
+      auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * {
+        const APInt &API = dyn_cast<ConstantInt>(CV)->getValue();
+        std::optional<uint64_t> InitIntOpt;
+        if (API.isNonNegative())
+          InitIntOpt = API.tryZExtValue();
+        else if (auto Temp = API.trySExtValue(); Temp.has_value())
+          // Transform a signed optional to unsigned optional.
+          InitIntOpt = (uint64_t)Temp.value();
+        return DIB.createConstantValueExpression(InitIntOpt.value());
+      };
+
+      const Constant *CV = GV->getInitializer();
+      Type *Ty = GV->getValueType();
+      if (Ty->isIntegerTy()) {
+        GVEs[0]->replaceOperandWith(1, createIntExpression(CV));
+      } else if (Ty->isFloatTy() || Ty->isDoubleTy()) {
+        const APFloat &APF = dyn_cast<ConstantFP>(CV)->getValueAPF();
+        DIExpression *NewExpr = DIB.createConstantValueExpression(
+            APF.bitcastToAPInt().getZExtValue());
+        GVEs[0]->replaceOperandWith(1, NewExpr);
+      } else if (Ty->isPointerTy()) {
+        if (isa<ConstantPointerNull>(CV)) {
+          GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(0));
+        } else {
+          if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
+            if (CE->getNumOperands() == 1) {
+              const Value *V = CE->getOperand(0);
+              const Constant *CV = dyn_cast<Constant>(V);
+              if (CV && !isa<GlobalValue>(CV))
+                if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
+                  GVEs[0]->replaceOperandWith(1, createIntExpression(CI));
+            }
+          }
+        }
+      }
+    }
+
     MadeChanges = true;
     M.eraseGlobalVariable(GV);
     ++NumGlobalConst;
diff --git a/llvm/test/Transforms/SCCP/pr50901.ll b/llvm/test/Transforms/SCCP/pr50901.ll
new file mode 100644
index 000000000000000..56961d2e32db41c
--- /dev/null
+++ b/llvm/test/Transforms/SCCP/pr50901.ll
@@ -0,0 +1,184 @@
+; RUN: opt -passes=ipsccp -S -o - < %s | FileCheck %s
+
+; Global variables g_11, g_22, g_33, g_44, g_55, g_66 and g_77
+; are not visible in the debugger.
+
+;  1	int       g_1 = -4;
+;  2	float     g_2 = 4.44;
+;  3	char      g_3 = 'a';
+;  4	unsigned  g_4 = 4;
+;  5	bool      g_5 = true;
+;  6	int      *g_6 = nullptr;
+;  7	float    *g_7 = nullptr;
+;  8
+;  9	static int       g_11 = -5;
+; 10	static float     g_22 = 5.55;
+; 11	static char      g_33 = 'b';
+; 12	static unsigned  g_44 = 5;
+; 13	static bool      g_55 = true;
+; 14	static int      *g_66 = nullptr;
+; 15	static float    *g_77 = (float *)(55 + 15);
+; 16
+; 17	void bar() {
+; 18	  g_1 = g_11;
+; 19	  g_2 = g_22;
+; 20	  g_3 = g_33;
+; 21	  g_4 = g_44;
+; 22	  g_5 = g_55;
+; 23	  g_6 = g_66;
+; 24	  g_7 = g_77;
+; 25	}
+; 26
+; 27	int main() {
+; 28	  {
+; 29	    bar();
+; 30	  }
+; 31	}
+
+; CHECK: ![[G1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG1:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18446744073709551611, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG1]] = distinct !DIGlobalVariable(name: "g_11", {{.*}}
+; CHECK: ![[G2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG2:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1085381018, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG2]] = distinct !DIGlobalVariable(name: "g_22", {{.*}}
+; CHECK: ![[G3:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG3:[0-9]+]], expr: !DIExpression(DW_OP_constu, 98, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG3]] = distinct !DIGlobalVariable(name: "g_33", {{.*}}
+; CHECK: ![[G4:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG4:[0-9]+]], expr: !DIExpression(DW_OP_constu, 5, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG4]] = distinct !DIGlobalVariable(name: "g_44", {{.*}}
+; CHECK: ![[G5:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG5:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG5]] = distinct !DIGlobalVariable(name: "g_55", {{.*}}
+; CHECK: ![[G6:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG6:[0-9]+]], expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG6]] = distinct !DIGlobalVariable(name: "g_66", {{.*}}
+; CHECK: ![[G7:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG7:[0-9]+]], expr: !DIExpression(DW_OP_constu, 70, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG7]] = distinct !DIGlobalVariable(name: "g_77", {{.*}}
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+ at g_1 = dso_local global i32 -4, align 4, !dbg !0
+ at g_2 = dso_local global float 0x4011C28F60000000, align 4, !dbg !8
+ at g_3 = dso_local global i8 97, align 1, !dbg !10
+ at g_4 = dso_local global i32 4, align 4, !dbg !13
+ at g_5 = dso_local global i8 1, align 1, !dbg !16
+ at g_6 = dso_local global ptr null, align 8, !dbg !19
+ at g_7 = dso_local global ptr null, align 8, !dbg !23
+ at _ZL4g_11 = internal global i32 -5, align 4, !dbg !25
+ at _ZL4g_22 = internal global float 0x4016333340000000, align 4, !dbg !27
+ at _ZL4g_33 = internal global i8 98, align 1, !dbg !29
+ at _ZL4g_44 = internal global i32 5, align 4, !dbg !31
+ at _ZL4g_55 = internal global i8 1, align 1, !dbg !33
+ at _ZL4g_66 = internal global ptr null, align 8, !dbg !35
+ at _ZL4g_77 = internal global ptr inttoptr (i64 70 to ptr), align 8, !dbg !37
+
+define dso_local void @_Z3barv() !dbg !46 {
+entry:
+  %0 = load i32, ptr @_ZL4g_11, align 4, !dbg !49, !tbaa !50
+  store i32 %0, ptr @g_1, align 4, !dbg !54, !tbaa !50
+  %1 = load float, ptr @_ZL4g_22, align 4, !dbg !55, !tbaa !56
+  store float %1, ptr @g_2, align 4, !dbg !58, !tbaa !56
+  %2 = load i8, ptr @_ZL4g_33, align 1, !dbg !59, !tbaa !60
+  store i8 %2, ptr @g_3, align 1, !dbg !61, !tbaa !60
+  %3 = load i32, ptr @_ZL4g_44, align 4, !dbg !62, !tbaa !50
+  store i32 %3, ptr @g_4, align 4, !dbg !63, !tbaa !50
+  %4 = load i8, ptr @_ZL4g_55, align 1, !dbg !64, !tbaa !65, !range !67, !noundef !68
+  %tobool = trunc i8 %4 to i1, !dbg !64
+  %frombool = zext i1 %tobool to i8, !dbg !69
+  store i8 %frombool, ptr @g_5, align 1, !dbg !69, !tbaa !65
+  %5 = load ptr, ptr @_ZL4g_66, align 8, !dbg !70, !tbaa !71
+  store ptr %5, ptr @g_6, align 8, !dbg !73, !tbaa !71
+  %6 = load ptr, ptr @_ZL4g_77, align 8, !dbg !74, !tbaa !71
+  store ptr %6, ptr @g_7, align 8, !dbg !75, !tbaa !71
+  ret void, !dbg !76
+}
+
+define dso_local noundef i32 @main() !dbg !77 {
+entry:
+  call void @_Z3barv(), !dbg !80
+  ret i32 0, !dbg !82
+}
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!39, !40, !41, !42, !43, !44}
+!llvm.ident = !{!45}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "g_1", scope: !2, file: !3, line: 1, type: !22, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !4, globals: !7, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "test.cpp", directory: "")
+!4 = !{!5}
+!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64)
+!6 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+!7 = !{!0, !8, !10, !13, !16, !19, !23, !25, !27, !29, !31, !33, !35, !37}
+!8 = !DIGlobalVariableExpression(var: !9, expr: !DIExpression())
+!9 = distinct !DIGlobalVariable(name: "g_2", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true)
+!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
+!11 = distinct !DIGlobalVariable(name: "g_3", scope: !2, file: !3, line: 3, type: !12, isLocal: false, isDefinition: true)
+!12 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression())
+!14 = distinct !DIGlobalVariable(name: "g_4", scope: !2, file: !3, line: 4, type: !15, isLocal: false, isDefinition: true)
+!15 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!16 = !DIGlobalVariableExpression(var: !17, expr: !DIExpression())
+!17 = distinct !DIGlobalVariable(name: "g_5", scope: !2, file: !3, line: 5, type: !18, isLocal: false, isDefinition: true)
+!18 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
+!19 = !DIGlobalVariableExpression(var: !20, expr: !DIExpression())
+!20 = distinct !DIGlobalVariable(name: "g_6", scope: !2, file: !3, line: 6, type: !21, isLocal: false, isDefinition: true)
+!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 64)
+!22 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!23 = !DIGlobalVariableExpression(var: !24, expr: !DIExpression())
+!24 = distinct !DIGlobalVariable(name: "g_7", scope: !2, file: !3, line: 7, type: !5, isLocal: false, isDefinition: true)
+!25 = !DIGlobalVariableExpression(var: !26, expr: !DIExpression())
+!26 = distinct !DIGlobalVariable(name: "g_11", linkageName: "_ZL4g_11", scope: !2, file: !3, line: 9, type: !22, isLocal: true, isDefinition: true)
+!27 = !DIGlobalVariableExpression(var: !28, expr: !DIExpression())
+!28 = distinct !DIGlobalVariable(name: "g_22", linkageName: "_ZL4g_22", scope: !2, file: !3, line: 10, type: !6, isLocal: true, isDefinition: true)
+!29 = !DIGlobalVariableExpression(var: !30, expr: !DIExpression())
+!30 = distinct !DIGlobalVariable(name: "g_33", linkageName: "_ZL4g_33", scope: !2, file: !3, line: 11, type: !12, isLocal: true, isDefinition: true)
+!31 = !DIGlobalVariableExpression(var: !32, expr: !DIExpression())
+!32 = distinct !DIGlobalVariable(name: "g_44", linkageName: "_ZL4g_44", scope: !2, file: !3, line: 12, type: !15, isLocal: true, isDefinition: true)
+!33 = !DIGlobalVariableExpression(var: !34, expr: !DIExpression())
+!34 = distinct !DIGlobalVariable(name: "g_55", linkageName: "_ZL4g_55", scope: !2, file: !3, line: 13, type: !18, isLocal: true, isDefinition: true)
+!35 = !DIGlobalVariableExpression(var: !36, expr: !DIExpression())
+!36 = distinct !DIGlobalVariable(name: "g_66", linkageName: "_ZL4g_66", scope: !2, file: !3, line: 14, type: !21, isLocal: true, isDefinition: true)
+!37 = !DIGlobalVariableExpression(var: !38, expr: !DIExpression())
+!38 = distinct !DIGlobalVariable(name: "g_77", linkageName: "_ZL4g_77", scope: !2, file: !3, line: 15, type: !5, isLocal: true, isDefinition: true)
+!39 = !{i32 7, !"Dwarf Version", i32 5}
+!40 = !{i32 2, !"Debug Info Version", i32 3}
+!41 = !{i32 1, !"wchar_size", i32 4}
+!42 = !{i32 8, !"PIC Level", i32 2}
+!43 = !{i32 7, !"PIE Level", i32 2}
+!44 = !{i32 7, !"uwtable", i32 2}
+!45 = !{!"clang version 18.0.0"}
+!46 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !3, file: !3, line: 17, type: !47, scopeLine: 17, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
+!47 = !DISubroutineType(types: !48)
+!48 = !{null}
+!49 = !DILocation(line: 18, column: 9, scope: !46)
+!50 = !{!51, !51, i64 0}
+!51 = !{!"int", !52, i64 0}
+!52 = !{!"omnipotent char", !53, i64 0}
+!53 = !{!"Simple C++ TBAA"}
+!54 = !DILocation(line: 18, column: 7, scope: !46)
+!55 = !DILocation(line: 19, column: 9, scope: !46)
+!56 = !{!57, !57, i64 0}
+!57 = !{!"float", !52, i64 0}
+!58 = !DILocation(line: 19, column: 7, scope: !46)
+!59 = !DILocation(line: 20, column: 9, scope: !46)
+!60 = !{!52, !52, i64 0}
+!61 = !DILocation(line: 20, column: 7, scope: !46)
+!62 = !DILocation(line: 21, column: 9, scope: !46)
+!63 = !DILocation(line: 21, column: 7, scope: !46)
+!64 = !DILocation(line: 22, column: 9, scope: !46)
+!65 = !{!66, !66, i64 0}
+!66 = !{!"bool", !52, i64 0}
+!67 = !{i8 0, i8 2}
+!68 = !{}
+!69 = !DILocation(line: 22, column: 7, scope: !46)
+!70 = !DILocation(line: 23, column: 9, scope: !46)
+!71 = !{!72, !72, i64 0}
+!72 = !{!"any pointer", !52, i64 0}
+!73 = !DILocation(line: 23, column: 7, scope: !46)
+!74 = !DILocation(line: 24, column: 9, scope: !46)
+!75 = !DILocation(line: 24, column: 7, scope: !46)
+!76 = !DILocation(line: 25, column: 1, scope: !46)
+!77 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 27, type: !78, scopeLine: 27, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
+!78 = !DISubroutineType(types: !79)
+!79 = !{!22}
+!80 = !DILocation(line: 29, column: 5, scope: !81)
+!81 = distinct !DILexicalBlock(scope: !77, file: !3, line: 28, column: 3)
+!82 = !DILocation(line: 31, column: 1, scope: !77)

>From 6311ca6830b0a311de173c7315c1abb7babd4c73 Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <carlos.alberto.enciso at gmail.com>
Date: Mon, 18 Sep 2023 12:29:17 +0100
Subject: [PATCH 2/4] [IPSCCP] Variable not visible at Og:

https://bugs.llvm.org/show_bug.cgi?id=51559
https://github.com/llvm/llvm-project/issues/50901

IPSCCP pass removes the global variable and does not
create a constant expression for the initializer value.
---
 llvm/lib/Transforms/IPO/SCCP.cpp     |  47 +++++++
 llvm/test/Transforms/SCCP/pr50901.ll | 184 +++++++++++++++++++++++++++
 2 files changed, 231 insertions(+)
 create mode 100644 llvm/test/Transforms/SCCP/pr50901.ll

diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp
index 84f5bbf7039416b..e09769e00148143 100644
--- a/llvm/lib/Transforms/IPO/SCCP.cpp
+++ b/llvm/lib/Transforms/IPO/SCCP.cpp
@@ -22,6 +22,7 @@
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/AttributeMask.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ModRef.h"
@@ -371,6 +372,52 @@ static bool runIPSCCP(
       StoreInst *SI = cast<StoreInst>(GV->user_back());
       SI->eraseFromParent();
     }
+
+    // Try to create a debug constant expression for the glbal variable
+    // initializer value.
+    SmallVector<DIGlobalVariableExpression *, 1> GVEs;
+    GV->getDebugInfo(GVEs);
+    if (GVEs.size() == 1) {
+      DIBuilder DIB(M);
+
+      // Create integer constant expression.
+      auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * {
+        const APInt &API = dyn_cast<ConstantInt>(CV)->getValue();
+        std::optional<uint64_t> InitIntOpt;
+        if (API.isNonNegative())
+          InitIntOpt = API.tryZExtValue();
+        else if (auto Temp = API.trySExtValue(); Temp.has_value())
+          // Transform a signed optional to unsigned optional.
+          InitIntOpt = (uint64_t)Temp.value();
+        return DIB.createConstantValueExpression(InitIntOpt.value());
+      };
+
+      const Constant *CV = GV->getInitializer();
+      Type *Ty = GV->getValueType();
+      if (Ty->isIntegerTy()) {
+        GVEs[0]->replaceOperandWith(1, createIntExpression(CV));
+      } else if (Ty->isFloatTy() || Ty->isDoubleTy()) {
+        const APFloat &APF = dyn_cast<ConstantFP>(CV)->getValueAPF();
+        DIExpression *NewExpr = DIB.createConstantValueExpression(
+            APF.bitcastToAPInt().getZExtValue());
+        GVEs[0]->replaceOperandWith(1, NewExpr);
+      } else if (Ty->isPointerTy()) {
+        if (isa<ConstantPointerNull>(CV)) {
+          GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(0));
+        } else {
+          if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
+            if (CE->getNumOperands() == 1) {
+              const Value *V = CE->getOperand(0);
+              const Constant *CV = dyn_cast<Constant>(V);
+              if (CV && !isa<GlobalValue>(CV))
+                if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
+                  GVEs[0]->replaceOperandWith(1, createIntExpression(CI));
+            }
+          }
+        }
+      }
+    }
+
     MadeChanges = true;
     M.eraseGlobalVariable(GV);
     ++NumGlobalConst;
diff --git a/llvm/test/Transforms/SCCP/pr50901.ll b/llvm/test/Transforms/SCCP/pr50901.ll
new file mode 100644
index 000000000000000..56961d2e32db41c
--- /dev/null
+++ b/llvm/test/Transforms/SCCP/pr50901.ll
@@ -0,0 +1,184 @@
+; RUN: opt -passes=ipsccp -S -o - < %s | FileCheck %s
+
+; Global variables g_11, g_22, g_33, g_44, g_55, g_66 and g_77
+; are not visible in the debugger.
+
+;  1	int       g_1 = -4;
+;  2	float     g_2 = 4.44;
+;  3	char      g_3 = 'a';
+;  4	unsigned  g_4 = 4;
+;  5	bool      g_5 = true;
+;  6	int      *g_6 = nullptr;
+;  7	float    *g_7 = nullptr;
+;  8
+;  9	static int       g_11 = -5;
+; 10	static float     g_22 = 5.55;
+; 11	static char      g_33 = 'b';
+; 12	static unsigned  g_44 = 5;
+; 13	static bool      g_55 = true;
+; 14	static int      *g_66 = nullptr;
+; 15	static float    *g_77 = (float *)(55 + 15);
+; 16
+; 17	void bar() {
+; 18	  g_1 = g_11;
+; 19	  g_2 = g_22;
+; 20	  g_3 = g_33;
+; 21	  g_4 = g_44;
+; 22	  g_5 = g_55;
+; 23	  g_6 = g_66;
+; 24	  g_7 = g_77;
+; 25	}
+; 26
+; 27	int main() {
+; 28	  {
+; 29	    bar();
+; 30	  }
+; 31	}
+
+; CHECK: ![[G1:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG1:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18446744073709551611, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG1]] = distinct !DIGlobalVariable(name: "g_11", {{.*}}
+; CHECK: ![[G2:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG2:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1085381018, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG2]] = distinct !DIGlobalVariable(name: "g_22", {{.*}}
+; CHECK: ![[G3:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG3:[0-9]+]], expr: !DIExpression(DW_OP_constu, 98, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG3]] = distinct !DIGlobalVariable(name: "g_33", {{.*}}
+; CHECK: ![[G4:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG4:[0-9]+]], expr: !DIExpression(DW_OP_constu, 5, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG4]] = distinct !DIGlobalVariable(name: "g_44", {{.*}}
+; CHECK: ![[G5:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG5:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG5]] = distinct !DIGlobalVariable(name: "g_55", {{.*}}
+; CHECK: ![[G6:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG6:[0-9]+]], expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG6]] = distinct !DIGlobalVariable(name: "g_66", {{.*}}
+; CHECK: ![[G7:[0-9]+]] = !DIGlobalVariableExpression(var: ![[DBG7:[0-9]+]], expr: !DIExpression(DW_OP_constu, 70, DW_OP_stack_value))
+; CHECK-DAG: ![[DBG7]] = distinct !DIGlobalVariable(name: "g_77", {{.*}}
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+ at g_1 = dso_local global i32 -4, align 4, !dbg !0
+ at g_2 = dso_local global float 0x4011C28F60000000, align 4, !dbg !8
+ at g_3 = dso_local global i8 97, align 1, !dbg !10
+ at g_4 = dso_local global i32 4, align 4, !dbg !13
+ at g_5 = dso_local global i8 1, align 1, !dbg !16
+ at g_6 = dso_local global ptr null, align 8, !dbg !19
+ at g_7 = dso_local global ptr null, align 8, !dbg !23
+ at _ZL4g_11 = internal global i32 -5, align 4, !dbg !25
+ at _ZL4g_22 = internal global float 0x4016333340000000, align 4, !dbg !27
+ at _ZL4g_33 = internal global i8 98, align 1, !dbg !29
+ at _ZL4g_44 = internal global i32 5, align 4, !dbg !31
+ at _ZL4g_55 = internal global i8 1, align 1, !dbg !33
+ at _ZL4g_66 = internal global ptr null, align 8, !dbg !35
+ at _ZL4g_77 = internal global ptr inttoptr (i64 70 to ptr), align 8, !dbg !37
+
+define dso_local void @_Z3barv() !dbg !46 {
+entry:
+  %0 = load i32, ptr @_ZL4g_11, align 4, !dbg !49, !tbaa !50
+  store i32 %0, ptr @g_1, align 4, !dbg !54, !tbaa !50
+  %1 = load float, ptr @_ZL4g_22, align 4, !dbg !55, !tbaa !56
+  store float %1, ptr @g_2, align 4, !dbg !58, !tbaa !56
+  %2 = load i8, ptr @_ZL4g_33, align 1, !dbg !59, !tbaa !60
+  store i8 %2, ptr @g_3, align 1, !dbg !61, !tbaa !60
+  %3 = load i32, ptr @_ZL4g_44, align 4, !dbg !62, !tbaa !50
+  store i32 %3, ptr @g_4, align 4, !dbg !63, !tbaa !50
+  %4 = load i8, ptr @_ZL4g_55, align 1, !dbg !64, !tbaa !65, !range !67, !noundef !68
+  %tobool = trunc i8 %4 to i1, !dbg !64
+  %frombool = zext i1 %tobool to i8, !dbg !69
+  store i8 %frombool, ptr @g_5, align 1, !dbg !69, !tbaa !65
+  %5 = load ptr, ptr @_ZL4g_66, align 8, !dbg !70, !tbaa !71
+  store ptr %5, ptr @g_6, align 8, !dbg !73, !tbaa !71
+  %6 = load ptr, ptr @_ZL4g_77, align 8, !dbg !74, !tbaa !71
+  store ptr %6, ptr @g_7, align 8, !dbg !75, !tbaa !71
+  ret void, !dbg !76
+}
+
+define dso_local noundef i32 @main() !dbg !77 {
+entry:
+  call void @_Z3barv(), !dbg !80
+  ret i32 0, !dbg !82
+}
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!39, !40, !41, !42, !43, !44}
+!llvm.ident = !{!45}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "g_1", scope: !2, file: !3, line: 1, type: !22, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !4, globals: !7, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "test.cpp", directory: "")
+!4 = !{!5}
+!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64)
+!6 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
+!7 = !{!0, !8, !10, !13, !16, !19, !23, !25, !27, !29, !31, !33, !35, !37}
+!8 = !DIGlobalVariableExpression(var: !9, expr: !DIExpression())
+!9 = distinct !DIGlobalVariable(name: "g_2", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true)
+!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
+!11 = distinct !DIGlobalVariable(name: "g_3", scope: !2, file: !3, line: 3, type: !12, isLocal: false, isDefinition: true)
+!12 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression())
+!14 = distinct !DIGlobalVariable(name: "g_4", scope: !2, file: !3, line: 4, type: !15, isLocal: false, isDefinition: true)
+!15 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!16 = !DIGlobalVariableExpression(var: !17, expr: !DIExpression())
+!17 = distinct !DIGlobalVariable(name: "g_5", scope: !2, file: !3, line: 5, type: !18, isLocal: false, isDefinition: true)
+!18 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean)
+!19 = !DIGlobalVariableExpression(var: !20, expr: !DIExpression())
+!20 = distinct !DIGlobalVariable(name: "g_6", scope: !2, file: !3, line: 6, type: !21, isLocal: false, isDefinition: true)
+!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 64)
+!22 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!23 = !DIGlobalVariableExpression(var: !24, expr: !DIExpression())
+!24 = distinct !DIGlobalVariable(name: "g_7", scope: !2, file: !3, line: 7, type: !5, isLocal: false, isDefinition: true)
+!25 = !DIGlobalVariableExpression(var: !26, expr: !DIExpression())
+!26 = distinct !DIGlobalVariable(name: "g_11", linkageName: "_ZL4g_11", scope: !2, file: !3, line: 9, type: !22, isLocal: true, isDefinition: true)
+!27 = !DIGlobalVariableExpression(var: !28, expr: !DIExpression())
+!28 = distinct !DIGlobalVariable(name: "g_22", linkageName: "_ZL4g_22", scope: !2, file: !3, line: 10, type: !6, isLocal: true, isDefinition: true)
+!29 = !DIGlobalVariableExpression(var: !30, expr: !DIExpression())
+!30 = distinct !DIGlobalVariable(name: "g_33", linkageName: "_ZL4g_33", scope: !2, file: !3, line: 11, type: !12, isLocal: true, isDefinition: true)
+!31 = !DIGlobalVariableExpression(var: !32, expr: !DIExpression())
+!32 = distinct !DIGlobalVariable(name: "g_44", linkageName: "_ZL4g_44", scope: !2, file: !3, line: 12, type: !15, isLocal: true, isDefinition: true)
+!33 = !DIGlobalVariableExpression(var: !34, expr: !DIExpression())
+!34 = distinct !DIGlobalVariable(name: "g_55", linkageName: "_ZL4g_55", scope: !2, file: !3, line: 13, type: !18, isLocal: true, isDefinition: true)
+!35 = !DIGlobalVariableExpression(var: !36, expr: !DIExpression())
+!36 = distinct !DIGlobalVariable(name: "g_66", linkageName: "_ZL4g_66", scope: !2, file: !3, line: 14, type: !21, isLocal: true, isDefinition: true)
+!37 = !DIGlobalVariableExpression(var: !38, expr: !DIExpression())
+!38 = distinct !DIGlobalVariable(name: "g_77", linkageName: "_ZL4g_77", scope: !2, file: !3, line: 15, type: !5, isLocal: true, isDefinition: true)
+!39 = !{i32 7, !"Dwarf Version", i32 5}
+!40 = !{i32 2, !"Debug Info Version", i32 3}
+!41 = !{i32 1, !"wchar_size", i32 4}
+!42 = !{i32 8, !"PIC Level", i32 2}
+!43 = !{i32 7, !"PIE Level", i32 2}
+!44 = !{i32 7, !"uwtable", i32 2}
+!45 = !{!"clang version 18.0.0"}
+!46 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !3, file: !3, line: 17, type: !47, scopeLine: 17, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
+!47 = !DISubroutineType(types: !48)
+!48 = !{null}
+!49 = !DILocation(line: 18, column: 9, scope: !46)
+!50 = !{!51, !51, i64 0}
+!51 = !{!"int", !52, i64 0}
+!52 = !{!"omnipotent char", !53, i64 0}
+!53 = !{!"Simple C++ TBAA"}
+!54 = !DILocation(line: 18, column: 7, scope: !46)
+!55 = !DILocation(line: 19, column: 9, scope: !46)
+!56 = !{!57, !57, i64 0}
+!57 = !{!"float", !52, i64 0}
+!58 = !DILocation(line: 19, column: 7, scope: !46)
+!59 = !DILocation(line: 20, column: 9, scope: !46)
+!60 = !{!52, !52, i64 0}
+!61 = !DILocation(line: 20, column: 7, scope: !46)
+!62 = !DILocation(line: 21, column: 9, scope: !46)
+!63 = !DILocation(line: 21, column: 7, scope: !46)
+!64 = !DILocation(line: 22, column: 9, scope: !46)
+!65 = !{!66, !66, i64 0}
+!66 = !{!"bool", !52, i64 0}
+!67 = !{i8 0, i8 2}
+!68 = !{}
+!69 = !DILocation(line: 22, column: 7, scope: !46)
+!70 = !DILocation(line: 23, column: 9, scope: !46)
+!71 = !{!72, !72, i64 0}
+!72 = !{!"any pointer", !52, i64 0}
+!73 = !DILocation(line: 23, column: 7, scope: !46)
+!74 = !DILocation(line: 24, column: 9, scope: !46)
+!75 = !DILocation(line: 24, column: 7, scope: !46)
+!76 = !DILocation(line: 25, column: 1, scope: !46)
+!77 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 27, type: !78, scopeLine: 27, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
+!78 = !DISubroutineType(types: !79)
+!79 = !{!22}
+!80 = !DILocation(line: 29, column: 5, scope: !81)
+!81 = distinct !DILexicalBlock(scope: !77, file: !3, line: 28, column: 3)
+!82 = !DILocation(line: 31, column: 1, scope: !77)

>From a1c2473c38c8c781ff7c539114d00bd1c05064f5 Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <carlos.alberto.enciso at gmail.com>
Date: Tue, 3 Oct 2023 11:02:24 +0100
Subject: [PATCH 3/4] [IPSCCP] Variable not visible at Og:

https://bugs.llvm.org/show_bug.cgi?id=51559
https://github.com/llvm/llvm-project/issues/50901

IPSCCP pass removes the global variable and does not
create a constant expression for the initializer value.

Address reviewers comments:
- Refactor the new code into a helper function.
- Use early returns to reduce nested ifs.
- Remove C-style casts.
- Add validation to detect posible nullopt.
---
 llvm/lib/Transforms/IPO/SCCP.cpp | 118 ++++++++++++++++++-------------
 1 file changed, 67 insertions(+), 51 deletions(-)

diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp
index e09769e00148143..01fc83ca4d53298 100644
--- a/llvm/lib/Transforms/IPO/SCCP.cpp
+++ b/llvm/lib/Transforms/IPO/SCCP.cpp
@@ -107,14 +107,71 @@ static void findReturnsToZap(Function &F,
   }
 }
 
-static bool runIPSCCP(
-    Module &M, const DataLayout &DL, FunctionAnalysisManager *FAM,
-    std::function<const TargetLibraryInfo &(Function &)> GetTLI,
-    std::function<TargetTransformInfo &(Function &)> GetTTI,
-    std::function<AssumptionCache &(Function &)> GetAC,
-    std::function<DominatorTree &(Function &)> GetDT,
-    std::function<BlockFrequencyInfo &(Function &)> GetBFI,
-    bool IsFuncSpecEnabled) {
+static void createDebugConstantExpression(Module &M, GlobalVariable *GV) {
+  SmallVector<DIGlobalVariableExpression *, 1> GVEs;
+  GV->getDebugInfo(GVEs);
+  if (GVEs.size() != 1)
+    return;
+
+  DIBuilder DIB(M);
+
+  // Create integer constant expression.
+  auto createIntegerExpression = [&DIB](const Constant *CV) -> DIExpression * {
+    const APInt &API = cast<ConstantInt>(CV)->getValue();
+    std::optional<uint64_t> InitIntOpt;
+    if (API.isNonNegative())
+      InitIntOpt = API.tryZExtValue();
+    else if (auto Temp = API.trySExtValue(); Temp.has_value())
+      // Transform a signed optional to unsigned optional.
+      InitIntOpt = static_cast<uint64_t>(Temp.value());
+    return InitIntOpt ? DIB.createConstantValueExpression(InitIntOpt.value())
+                      : nullptr;
+  };
+
+  const Constant *CV = GV->getInitializer();
+  Type *Ty = GV->getValueType();
+  if (Ty->isIntegerTy()) {
+    DIExpression *InitExpr = createIntegerExpression(CV);
+    if (InitExpr)
+      GVEs[0]->replaceOperandWith(1, InitExpr);
+    return;
+  }
+
+  if (Ty->isFloatTy() || Ty->isDoubleTy()) {
+    const APFloat &APF = cast<ConstantFP>(CV)->getValueAPF();
+    GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(
+                                       APF.bitcastToAPInt().getZExtValue()));
+    return;
+  }
+
+  if (!Ty->isPointerTy())
+    return;
+
+  if (isa<ConstantPointerNull>(CV)) {
+    GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(0));
+    return;
+  }
+  if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
+      CE->getNumOperands() == 1) {
+    const Value *V = CE->getOperand(0);
+    const Constant *CV = dyn_cast<Constant>(V);
+    if (CV && !isa<GlobalValue>(CV);
+        const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
+      DIExpression *InitExpr = createIntegerExpression(CI);
+      if (InitExpr)
+        GVEs[0]->replaceOperandWith(1, InitExpr);
+    }
+  }
+}
+
+static bool
+runIPSCCP(Module &M, const DataLayout &DL, FunctionAnalysisManager *FAM,
+          std::function<const TargetLibraryInfo &(Function &)> GetTLI,
+          std::function<TargetTransformInfo &(Function &)> GetTTI,
+          std::function<AssumptionCache &(Function &)> GetAC,
+          std::function<DominatorTree &(Function &)> GetDT,
+          std::function<BlockFrequencyInfo &(Function &)> GetBFI,
+          bool IsFuncSpecEnabled) {
   SCCPSolver Solver(DL, GetTLI, M.getContext());
   FunctionSpecializer Specializer(Solver, M, FAM, GetBFI, GetTLI, GetTTI,
                                   GetAC);
@@ -373,50 +430,9 @@ static bool runIPSCCP(
       SI->eraseFromParent();
     }
 
-    // Try to create a debug constant expression for the glbal variable
+    // Try to create a debug constant expression for the global variable
     // initializer value.
-    SmallVector<DIGlobalVariableExpression *, 1> GVEs;
-    GV->getDebugInfo(GVEs);
-    if (GVEs.size() == 1) {
-      DIBuilder DIB(M);
-
-      // Create integer constant expression.
-      auto createIntExpression = [&DIB](const Constant *CV) -> DIExpression * {
-        const APInt &API = dyn_cast<ConstantInt>(CV)->getValue();
-        std::optional<uint64_t> InitIntOpt;
-        if (API.isNonNegative())
-          InitIntOpt = API.tryZExtValue();
-        else if (auto Temp = API.trySExtValue(); Temp.has_value())
-          // Transform a signed optional to unsigned optional.
-          InitIntOpt = (uint64_t)Temp.value();
-        return DIB.createConstantValueExpression(InitIntOpt.value());
-      };
-
-      const Constant *CV = GV->getInitializer();
-      Type *Ty = GV->getValueType();
-      if (Ty->isIntegerTy()) {
-        GVEs[0]->replaceOperandWith(1, createIntExpression(CV));
-      } else if (Ty->isFloatTy() || Ty->isDoubleTy()) {
-        const APFloat &APF = dyn_cast<ConstantFP>(CV)->getValueAPF();
-        DIExpression *NewExpr = DIB.createConstantValueExpression(
-            APF.bitcastToAPInt().getZExtValue());
-        GVEs[0]->replaceOperandWith(1, NewExpr);
-      } else if (Ty->isPointerTy()) {
-        if (isa<ConstantPointerNull>(CV)) {
-          GVEs[0]->replaceOperandWith(1, DIB.createConstantValueExpression(0));
-        } else {
-          if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
-            if (CE->getNumOperands() == 1) {
-              const Value *V = CE->getOperand(0);
-              const Constant *CV = dyn_cast<Constant>(V);
-              if (CV && !isa<GlobalValue>(CV))
-                if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
-                  GVEs[0]->replaceOperandWith(1, createIntExpression(CI));
-            }
-          }
-        }
-      }
-    }
+    createDebugConstantExpression(M, GV);
 
     MadeChanges = true;
     M.eraseGlobalVariable(GV);

>From fc238650f397aebf8f880aa06ef66e94e275c297 Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <carlos.alberto.enciso at gmail.com>
Date: Wed, 4 Oct 2023 07:12:57 +0100
Subject: [PATCH 4/4] [IPSCCP] Variable not visible at Og:

https://bugs.llvm.org/show_bug.cgi?id=51559
https://github.com/llvm/llvm-project/issues/50901

IPSCCP pass removes the global variable and does not
create a constant expression for the initializer value.

Address reviewers comments:
- Refactor the new code into a helper function.
- Use early returns to reduce nested ifs.
- Remove C-style casts.
- Add validation to detect posible nullopt.
- Collapse conditions in a single if.
- Remove 'has_value'.
---
 llvm/lib/Transforms/IPO/SCCP.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp
index 01fc83ca4d53298..194e63c4b1db9fa 100644
--- a/llvm/lib/Transforms/IPO/SCCP.cpp
+++ b/llvm/lib/Transforms/IPO/SCCP.cpp
@@ -121,9 +121,9 @@ static void createDebugConstantExpression(Module &M, GlobalVariable *GV) {
     std::optional<uint64_t> InitIntOpt;
     if (API.isNonNegative())
       InitIntOpt = API.tryZExtValue();
-    else if (auto Temp = API.trySExtValue(); Temp.has_value())
+    else if (auto Temp = API.trySExtValue())
       // Transform a signed optional to unsigned optional.
-      InitIntOpt = static_cast<uint64_t>(Temp.value());
+      InitIntOpt = static_cast<uint64_t>(*Temp);
     return InitIntOpt ? DIB.createConstantValueExpression(InitIntOpt.value())
                       : nullptr;
   };



More information about the cfe-commits mailing list