[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2023-02-27 Thread Mikael Holmén via Phabricator via cfe-commits
uabelho added a comment.

I noticed that gvn-hoist doesn't handle this very nicely, I just wrote 
https://github.com/llvm/llvm-project/issues/61023


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2023-02-16 Thread Nick Desaulniers via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG329ef60f3e21: [Clang] support for outputs along indirect 
edges of asm goto (authored by nickdesaulniers).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2023-02-16 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 498157.
nickdesaulniers added a comment.

- final rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2023-02-06 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 495175.
nickdesaulniers added a comment.

- rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2023-02-02 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers marked 2 inline comments as done.
nickdesaulniers added inline comments.



Comment at: clang/docs/LanguageExtensions.rst:1584
+Outputs may be used along any branches from the ``asm goto`` whether the
+branches are taken or not.
 

void wrote:
> efriedma wrote:
> > Maybe put a note about earlier releases, so people don't get confused if 
> > they use newer documentation than their version of clang.
> > 
> > Is there any chance we want a dedicated __has_extension flag?
> > Is there any chance we want a dedicated __has_extension flag?
> 
> Might not be a bad idea just in case they have more than one compiler version 
> they're using. Then again, if they add code to use this feature, they're 
> fairly committed to the assumption that it'll "just work" even with a 
> __has_extension flag...(Remember that we currently don't actually warn if 
> they're using the outputs on the indirect branch. We just specify that such 
> behavior is undefined.)
> 
> I think a strongly worded note here that it's available with Clang 16+ (or 
> whatever) is going to be slightly better. It'll force them to use macros to 
> support multiple compiler versions, making their code wicked ugly, and them 
> possibly coming up with better ways to ensure that the correct compiler is 
> used for this feature.
I've added that as a separate commit https://reviews.llvm.org/D143205 to not 
hold this up. PTAL. Open to better names for the identifier.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2023-01-31 Thread Bill Wendling via Phabricator via cfe-commits
void accepted this revision.
void added a comment.
This revision is now accepted and ready to land.

One small comment about the documentation but L:GTM.




Comment at: clang/docs/LanguageExtensions.rst:1584
+Outputs may be used along any branches from the ``asm goto`` whether the
+branches are taken or not.
 

efriedma wrote:
> Maybe put a note about earlier releases, so people don't get confused if they 
> use newer documentation than their version of clang.
> 
> Is there any chance we want a dedicated __has_extension flag?
> Is there any chance we want a dedicated __has_extension flag?

Might not be a bad idea just in case they have more than one compiler version 
they're using. Then again, if they add code to use this feature, they're fairly 
committed to the assumption that it'll "just work" even with a __has_extension 
flag...(Remember that we currently don't actually warn if they're using the 
outputs on the indirect branch. We just specify that such behavior is 
undefined.)

I think a strongly worded note here that it's available with Clang 16+ (or 
whatever) is going to be slightly better. It'll force them to use macros to 
support multiple compiler versions, making their code wicked ugly, and them 
possibly coming up with better ways to ensure that the correct compiler is used 
for this feature.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2023-01-25 Thread Eli Friedman via Phabricator via cfe-commits
efriedma added inline comments.



Comment at: clang/docs/LanguageExtensions.rst:1584
+Outputs may be used along any branches from the ``asm goto`` whether the
+branches are taken or not.
 

Maybe put a note about earlier releases, so people don't get confused if they 
use newer documentation than their version of clang.

Is there any chance we want a dedicated __has_extension flag?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2023-01-24 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 491857.
nickdesaulniers marked 3 inline comments as done.
nickdesaulniers added a comment.

- use densemap, update release note, use !empty rather than size as per @void


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT: 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2023-01-18 Thread Bill Wendling via Phabricator via cfe-commits
void added inline comments.



Comment at: clang/docs/ReleaseNotes.rst:199
+  guaranteed (and necessary to support outputs along indirect edges, which is
+  now supported as of this release).
+

Is it worth it to mention that this change makes Clang's behavior with regards 
to your example here consistent with GCC's behavior?



Comment at: clang/lib/CodeGen/CGStmt.cpp:2814
+  // A 2D vector, indexed by indirect destination, then ResultReg.
+  std::vector> CBRRegResults;
   if (IsGCCAsmGoto) {

It seems as if you really want a map indexed by the `BasicBlock*`. So something 
like this:

```
DenseMap> // 4 should be enough for 
anyone.
```

That way you can iterate over `CBR->getIndirectDests()` instead of having to 
use an iterator.



Comment at: clang/lib/CodeGen/CGStmt.cpp:2868
+  // CBRRegResults rather than RegResults.
+  if (IsGCCAsmGoto && CBRRegResults.size()) {
+for (unsigned i = 0, e = CBR->getNumIndirectDests(); i != e; ++i) {

Could probably use `!CBRRegResults.empty()` instead of `.size()`. The first 
should be `O(1)` (granted `.size()` probably should be too, but `.empty()` is 
more explicit anyway).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2023-01-18 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 490246.
nickdesaulniers added a comment.

- rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2023-01-10 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 487929.
nickdesaulniers added a comment.

- rebase, format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-12-21 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers added a comment.

Ready for review:

1. https://reviews.llvm.org/D135997
2. https://reviews.llvm.org/D140166
3. https://reviews.llvm.org/D139861
4. https://reviews.llvm.org/D139872
5. https://reviews.llvm.org/D139883
6. https://reviews.llvm.org/D139970
7. https://reviews.llvm.org/D140160
8. https://reviews.llvm.org/D137113
9. https://reviews.llvm.org/D136497


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-12-21 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 484678.
nickdesaulniers added a comment.

- add clang release notes from D138078  and 
new one for new feature.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-12-21 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 484671.
nickdesaulniers edited the summary of this revision.
nickdesaulniers added a comment.

- rebase, drop callbrpad inst


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-12-07 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers added a comment.

Probably should copy the release note change from 
https://reviews.llvm.org/D138078.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-12-07 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 480993.
nickdesaulniers edited the summary of this revision.
nickdesaulniers added a comment.

- rebase, use new callbrpad inst


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,163 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[TMP2:%.*]] = callbrpad i32 [[TMP0]]
+// CHECK-NEXT:store i32 [[TMP2]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[TMP2:%.*]] = callbrpad { i32, i32 } [[TMP0]]
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP2]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP2]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[TMP3:%.*]] = 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-31 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers added inline comments.



Comment at: clang/lib/CodeGen/CGStmt.cpp:2868-2873
+  // If we happen to share the same indirect and default dest, don't re-add
+  // stores. That was done for the default destination in the above call to
+  // EmitAsmStores.
+  llvm::BasicBlock *Succ = CBR->getIndirectDest(i);
+  if (Succ == CBR->getDefaultDest())
+continue;

nickdesaulniers wrote:
> void wrote:
> > nickdesaulniers wrote:
> > > nickdesaulniers wrote:
> > > > I'm not sure that I need to handle this case (of a callbr with the same 
> > > > indirect destination as the default destination).  That might result 
> > > > from optimizations, but I don't think clang can or will generate such 
> > > > IR.  Maybe I should turn this into an: `assert(CBR->getIndirectDest(i) 
> > > > != CBR->getDefaultDest(i) && "We already emitted asm stores in the 
> > > > default dest");`?
> > > Yeah, it's impossible. While a CallBrInst can have a same indirect 
> > > destination as the default destination as a result of optimizations, 
> > > above we always create an `"asm.fallthrough"` block that is distinct from 
> > > any of the named labels from the `asm goto`.
> > It could only happen with something like this:
> > 
> > ```
> > asm goto (...  indirect);
> > 
> > indirect:;
> > ```
> > 
> > In that simplified case, it looks like clang emits this:
> > 
> > ```
> > define dso_local void @foo() #0 {
> >   callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* 
> > blockaddress(@foo, %2)) #1
> >   to label %1 [label %2], !srcloc !6
> > 
> > 1:; preds = %0
> >   br label %2
> > 
> > 2:; preds = %1, %0
> >   ret void
> > }
> > ```
> > 
> > So it's probably safe to make this an assert.
> Oh, it's not just the default and indirects sharing, but what if the same 
> indirect is listed twice?  I should add a test for that...i.e.
> 
> ```
> asm goto (...  indirect,indirect);
> ```
Oh, right, we don't allow that.

```
error: duplicate use of asm operand name "indirect"
note: asm operand name "indirect" first referenced here
```

I'm going to leave these asserts out and mark this thread done, but please 
reopen this thread with a new comment if you feel strongly that I should add it 
back (`assert(CBR->getIndirectDest(i) != CBR->getDefaultDest(i) && "We already 
emitted asm stores in the default dest");`).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-31 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 472152.
nickdesaulniers marked an inline comment as done.
nickdesaulniers added a comment.

- reroll for a new sha so that phab unmarks this as "changes planned"


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-31 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers added inline comments.



Comment at: clang/lib/CodeGen/CGStmt.cpp:2868-2873
+  // If we happen to share the same indirect and default dest, don't re-add
+  // stores. That was done for the default destination in the above call to
+  // EmitAsmStores.
+  llvm::BasicBlock *Succ = CBR->getIndirectDest(i);
+  if (Succ == CBR->getDefaultDest())
+continue;

void wrote:
> nickdesaulniers wrote:
> > nickdesaulniers wrote:
> > > I'm not sure that I need to handle this case (of a callbr with the same 
> > > indirect destination as the default destination).  That might result from 
> > > optimizations, but I don't think clang can or will generate such IR.  
> > > Maybe I should turn this into an: `assert(CBR->getIndirectDest(i) != 
> > > CBR->getDefaultDest(i) && "We already emitted asm stores in the default 
> > > dest");`?
> > Yeah, it's impossible. While a CallBrInst can have a same indirect 
> > destination as the default destination as a result of optimizations, above 
> > we always create an `"asm.fallthrough"` block that is distinct from any of 
> > the named labels from the `asm goto`.
> It could only happen with something like this:
> 
> ```
> asm goto (...  indirect);
> 
> indirect:;
> ```
> 
> In that simplified case, it looks like clang emits this:
> 
> ```
> define dso_local void @foo() #0 {
>   callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* 
> blockaddress(@foo, %2)) #1
>   to label %1 [label %2], !srcloc !6
> 
> 1:; preds = %0
>   br label %2
> 
> 2:; preds = %1, %0
>   ret void
> }
> ```
> 
> So it's probably safe to make this an assert.
Oh, it's not just the default and indirects sharing, but what if the same 
indirect is listed twice?  I should add a test for that...i.e.

```
asm goto (...  indirect,indirect);
```


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-31 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 472144.
nickdesaulniers added a comment.

- remove unnecssary asserts


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-31 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers added inline comments.



Comment at: clang/lib/CodeGen/CGStmt.cpp:2868-2873
+  // If we happen to share the same indirect and default dest, don't re-add
+  // stores. That was done for the default destination in the above call to
+  // EmitAsmStores.
+  llvm::BasicBlock *Succ = CBR->getIndirectDest(i);
+  if (Succ == CBR->getDefaultDest())
+continue;

nickdesaulniers wrote:
> I'm not sure that I need to handle this case (of a callbr with the same 
> indirect destination as the default destination).  That might result from 
> optimizations, but I don't think clang can or will generate such IR.  Maybe I 
> should turn this into an: `assert(CBR->getIndirectDest(i) != 
> CBR->getDefaultDest(i) && "We already emitted asm stores in the default 
> dest");`?
Yeah, it's impossible. While a CallBrInst can have a same indirect destination 
as the default destination as a result of optimizations, above we always create 
an `"asm.fallthrough"` block that is distinct from any of the named labels from 
the `asm goto`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-31 Thread Bill Wendling via Phabricator via cfe-commits
void added inline comments.



Comment at: clang/lib/CodeGen/CGStmt.cpp:2868-2873
+  // If we happen to share the same indirect and default dest, don't re-add
+  // stores. That was done for the default destination in the above call to
+  // EmitAsmStores.
+  llvm::BasicBlock *Succ = CBR->getIndirectDest(i);
+  if (Succ == CBR->getDefaultDest())
+continue;

nickdesaulniers wrote:
> I'm not sure that I need to handle this case (of a callbr with the same 
> indirect destination as the default destination).  That might result from 
> optimizations, but I don't think clang can or will generate such IR.  Maybe I 
> should turn this into an: `assert(CBR->getIndirectDest(i) != 
> CBR->getDefaultDest(i) && "We already emitted asm stores in the default 
> dest");`?
It could only happen with something like this:

```
asm goto (...  indirect);

indirect:;
```

In that simplified case, it looks like clang emits this:

```
define dso_local void @foo() #0 {
  callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* 
blockaddress(@foo, %2)) #1
  to label %1 [label %2], !srcloc !6

1:; preds = %0
  br label %2

2:; preds = %1, %0
  ret void
}
```

So it's probably safe to make this an assert.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-31 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers planned changes to this revision.
nickdesaulniers added inline comments.



Comment at: clang/lib/CodeGen/CGStmt.cpp:2867
+for (unsigned i = 0, e = CBR->getNumIndirectDests(); i != e; ++i) {
+  assert(CBRRegResults[i].size() == ResultRegTypes.size());
+  // If we happen to share the same indirect and default dest, don't re-add

Oh, I can remove this now, I moved it into `EmitAsmStores`.



Comment at: clang/lib/CodeGen/CGStmt.cpp:2868-2873
+  // If we happen to share the same indirect and default dest, don't re-add
+  // stores. That was done for the default destination in the above call to
+  // EmitAsmStores.
+  llvm::BasicBlock *Succ = CBR->getIndirectDest(i);
+  if (Succ == CBR->getDefaultDest())
+continue;

I'm not sure that I need to handle this case (of a callbr with the same 
indirect destination as the default destination).  That might result from 
optimizations, but I don't think clang can or will generate such IR.  Maybe I 
should turn this into an: `assert(CBR->getIndirectDest(i) != 
CBR->getDefaultDest(i) && "We already emitted asm stores in the default 
dest");`?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-31 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 472136.
nickdesaulniers added a comment.

- rebase on D137113 , add comment


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-31 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers added inline comments.



Comment at: clang/lib/CodeGen/CGStmt.cpp:2850
 
   assert(RegResults.size() == ResultRegTypes.size());
   assert(RegResults.size() == ResultTruncRegTypes.size());

nickdesaulniers wrote:
> void wrote:
> > Should these asserts (or some of them) be moved into `EmitAsmStores()`?
> Ah, yeah, let me add those to D137113.
Now done in D137113.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-31 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers added inline comments.



Comment at: clang/lib/CodeGen/CGStmt.cpp:2362
+  // a pointer.
+  if (TruncTy->isFloatingPointTy())
+Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);

nickdesaulniers wrote:
> void wrote:
> > This looks like a direct copy from below (which is fine). I'm a bit iffy on 
> > whether this covers *all* of the value types that could come through here...
> Note: this code was simply moved wholesale.  If value types are missing, that 
> is a pre-existing bug and should be a prerequisite to fix for this patch.
> 
> I've broken out D137113 as a child patch to make that clearer.
s/should/shouldn't/


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-31 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers planned changes to this revision.
nickdesaulniers added a comment.

In D136497#3889938 , @void wrote:

> It might be easier to see the main changes here if you submit the (very nice) 
> refactoring of `EmitAsmStores` first.

D137113  TODO(Nick): rebase on D137113 





Comment at: clang/lib/CodeGen/CGStmt.cpp:2358
+// the expression, do the conversion.
+if (ResultRegTypes[i] != ResultTruncRegTypes[i]) {
+

void wrote:
> s/ResultTruncRegTypes[i]/TruncTy/
Done in D137113



Comment at: clang/lib/CodeGen/CGStmt.cpp:2362
+  // a pointer.
+  if (TruncTy->isFloatingPointTy())
+Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);

void wrote:
> This looks like a direct copy from below (which is fine). I'm a bit iffy on 
> whether this covers *all* of the value types that could come through here...
Note: this code was simply moved wholesale.  If value types are missing, that 
is a pre-existing bug and should be a prerequisite to fix for this patch.

I've broken out D137113 as a child patch to make that clearer.



Comment at: clang/lib/CodeGen/CGStmt.cpp:2850
 
   assert(RegResults.size() == ResultRegTypes.size());
   assert(RegResults.size() == ResultTruncRegTypes.size());

void wrote:
> Should these asserts (or some of them) be moved into `EmitAsmStores()`?
Ah, yeah, let me add those to D137113.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-27 Thread Bill Wendling via Phabricator via cfe-commits
void added a comment.

It might be easier to see the main changes here if you submit the (very nice) 
refactoring of `EmitAsmStores` first.




Comment at: clang/lib/CodeGen/CGStmt.cpp:2358
+// the expression, do the conversion.
+if (ResultRegTypes[i] != ResultTruncRegTypes[i]) {
+

s/ResultTruncRegTypes[i]/TruncTy/



Comment at: clang/lib/CodeGen/CGStmt.cpp:2362
+  // a pointer.
+  if (TruncTy->isFloatingPointTy())
+Tmp = Builder.CreateFPTrunc(Tmp, TruncTy);

This looks like a direct copy from below (which is fine). I'm a bit iffy on 
whether this covers *all* of the value types that could come through here...



Comment at: clang/lib/CodeGen/CGStmt.cpp:2850
 
   assert(RegResults.size() == ResultRegTypes.size());
   assert(RegResults.size() == ResultTruncRegTypes.size());

Should these asserts (or some of them) be moved into `EmitAsmStores()`?



Comment at: clang/lib/CodeGen/CGStmt.cpp:2862
+
+  if (IsGCCAsmGoto && CBRRegResults.size()) {
+for (unsigned i = 0, e = CBR->getNumIndirectDests(); i != e; ++i) {

nit: Could you add a comment explaining that we're calling `EmitAsmStores` for 
asm goto's indirect branches? I was slightly confused about why we were calling 
`EmitAsmStores` more than once. :)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-21 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 469782.
nickdesaulniers added a comment.

- update LanguageExtensions doc


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-21 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers added a comment.

Note to reviewers: I expect this to be one of a 3 part progression.

1. Fix DomTree D135997 
2. Fix front end D136497 
3. Fix back end (TODO)

Hopefully that's it; famous last words...


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-21 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 469767.
nickdesaulniers added a comment.

- git clang-format HEAD~


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-21 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers updated this revision to Diff 469764.
nickdesaulniers edited the summary of this revision.
nickdesaulniers added a comment.

- add note to commit message (let's see if phab captures what I wrote, used arc 
diff --verbatim)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136497/new/

https://reviews.llvm.org/D136497

Files:
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:[[TMP1:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH4:%.*]] [label %z.split9], !srcloc !5
+// CHECK:   asm.fallthrough4:
+// CHECK-NEXT:[[ASMRESULT5:%.*]] = extractvalue { i32, i32 } [[TMP1]], 0
+// CHECK-NEXT:[[ASMRESULT6:%.*]] = extractvalue { i32, i32 } [[TMP1]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT5]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT6]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP2:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP2]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { 

[PATCH] D136497: [Clang] support for outputs along indirect edges of asm goto

2022-10-21 Thread Nick Desaulniers via Phabricator via cfe-commits
nickdesaulniers created this revision.
nickdesaulniers added reviewers: nikic, void, jyknight, efriedma, craig.topper.
Herald added a subscriber: StephenFan.
Herald added a project: All.
nickdesaulniers requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Initial support for asm goto w/ outputs (D69876 
) only supported outputs
along the "default" (aka "fallthrough") edge.

We can support outputs along all edges by repeating the same pattern of
stores along the indirect edges that we allready do for the default
edge.  One complication is that these indirect edges may be critical
edges which would need to be split. Another issue is that mid-codgen of
LLVM IR, the control flow graph might not reflect the control flow of
the final function.

To avoid this "chicken and the egg" problem assume that any given
indirect edge may become a critical edge, and pro-actively split it.
This is unnecessary if the edge does not become critical, but LLVM will
optimize such cases via tail duplication.

Fixes: https://github.com/llvm/llvm-project/issues/53562


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136497

Files:
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/asm-goto.c
  clang/test/CodeGen/asm-goto2.c
  clang/test/Modules/asm-goto.c

Index: clang/test/Modules/asm-goto.c
===
--- clang/test/Modules/asm-goto.c
+++ clang/test/Modules/asm-goto.c
@@ -5,7 +5,7 @@
 
 // CHECK-LABEL: define {{.*}} @foo(
 // CHECK: callbr {{.*}} "=r,!i{{.*}}()
-// CHECK-NEXT: to label %asm.fallthrough [label %indirect]
+// CHECK-NEXT: to label %asm.fallthrough [label %indirect.split]
 
 int bar(void) {
   return foo();
Index: clang/test/CodeGen/asm-goto2.c
===
--- /dev/null
+++ clang/test/CodeGen/asm-goto2.c
@@ -0,0 +1,156 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -O0 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK-LABEL: @test0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr i32 asm "", "=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !2
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:store i32 [[TMP0]], ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test0 (void) {
+  int ret;
+  asm goto ("" : "=r"(ret):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !3
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4
+// CHECK-NEXT:store i32 42, ptr [[RET]], align 4
+// CHECK-NEXT:br label [[Z:%.*]]
+// CHECK:   z:
+// CHECK-NEXT:[[TMP1:%.*]] = load i32, ptr [[RET]], align 4
+// CHECK-NEXT:ret i32 [[TMP1]]
+// CHECK:   z.split:
+// CHECK-NEXT:[[ASMRESULT2:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT3:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT2]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT3]], ptr [[B]], align 4
+// CHECK-NEXT:br label [[Z]]
+//
+int test1 (void) {
+  int ret, b;
+  asm goto ("" : "=r"(ret), "=r"(b):::z);
+  ret = 42;
+z:
+  return ret;
+}
+
+// CHECK-LABEL: @test2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RET:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[B:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[TMP0:%.*]] = callbr { i32, i32 } asm "", "=r,=r,!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1]]
+// CHECK-NEXT:to label [[ASM_FALLTHROUGH:%.*]] [label %z.split], !srcloc !4
+// CHECK:   asm.fallthrough:
+// CHECK-NEXT:[[ASMRESULT:%.*]] = extractvalue { i32, i32 } [[TMP0]], 0
+// CHECK-NEXT:[[ASMRESULT1:%.*]] = extractvalue { i32, i32 } [[TMP0]], 1
+// CHECK-NEXT:store i32 [[ASMRESULT]], ptr [[RET]], align 4
+// CHECK-NEXT:store i32 [[ASMRESULT1]], ptr [[B]], align 4