public inbox for llvm@lists.linux.dev
 help / color / mirror / Atom feed
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
To: ndesaulniers <ndesaulniers@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>,
	llvm <llvm@lists.linux.dev>,  Bill Wendling <morbo@google.com>,
	 James Y Knight <jyknight@google.com>,
	 Eli Friedman <efriedma@quicinc.com>
Subject: Re: clang asm goto issue small reproducer
Date: Thu, 16 Dec 2021 11:39:30 -0500 (EST)	[thread overview]
Message-ID: <1302544343.35446.1639672770172.JavaMail.zimbra@efficios.com> (raw)
In-Reply-To: <CAKwvOdndCue_E4eE1_bnGisrPnmUY7vRb_FP_TMs4bQRTOi8Rw@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 3628 bytes --]

Hi Nick,

Here is the result of:

opt-13 -passes='gvn,gvn-hoist,gvn-sink,print<memoryssa>' -filter-print-funcs=this_cpu_list_pop test-asm.ll -o /dev/null 2> test-asm.gvn.ll
opt-13 -passes='gvn,gvn-hoist,gvn-sink,print<memoryssa>' -filter-print-funcs=this_cpu_list_pop test.ll -o /dev/null 2> test.gvn.ll

I notice a missing MemoryPhi in the case without the extra asm("").

Thanks,

Mathieu

----- On Dec 15, 2021, at 7:25 PM, ndesaulniers ndesaulniers@google.com wrote:

> On Wed, Dec 15, 2021 at 4:18 PM Nick Desaulniers
> <ndesaulniers@google.com> wrote:
>>
>> On Wed, Dec 15, 2021 at 3:50 PM Nick Desaulniers
>> <ndesaulniers@google.com> wrote:
>> >
>> > On Wed, Dec 15, 2021 at 2:06 PM Mathieu Desnoyers
>> > <mathieu.desnoyers@efficios.com> wrote:
>> > >
>> > > Hi Nick,
>> > >
>> > > I have a small reproducer for the asm goto issue we discussed over irc. I have
>> > > axed away all code that is not the problematic function by hand. Hopefully this
>> > > won't change the overall optimization context too much.
>> >
>> > If I cut the compilation pipeline off at after "middle-end"
>> > optimizations, I can see that `this_cpu_list_pop` returns `NULL` for
>> > test.c while in test-asm.c, it's a phi node of either NULL or head
>> > (which looks correct; for the test-asm.c case).
>> >
>> > "GVNPass" seems to be converting
>> >
>> > return:                                           ; preds =
>> > %cleanup.thread19, %cleanup.thread
>> >   %retval.118 = phi %struct.percpu_list_node* [ %9, %cleanup.thread ],
>> > [ null, %cleanup.thread19 ]
>> >   ret %struct.percpu_list_node* %retval.118
>> >
>> > into:
>> >
>> > return:                                           ; preds =
>> > %cleanup.thread19, %cleanup.thread
>> >   ret %struct.percpu_list_node* null
>> >
>> > Which drops the
>> >   %9 = load %struct.percpu_list_node*, %struct.percpu_list_node**
>> > %head, align 8, !tbaa !9
>>
>> Ah, Eli pointed out that I'm chasing the wrong squirrel. From test.c we have:
>>
>> struct percpu_list_node *head;
>> load = (intptr_t *)&head;
>> ret = rseq_cmpnev_storeoffp_load(targetptr, expectnot,
>>      offset, load, cpu);
>>
>> then in rseq_cmpnev_storeoffp_load():
>> __asm__ __volatile__ goto (
>>   :
>>   :
>> [load] "m" (*load));
>>
>> Did we ever initialize head?  Isn't this equivalent to:
>>
>> int* foo (void) {
>>   int *head;
>>   int **load;
>>   load = &head;
>>   asm(""::"m"(*load):"memory");
>>   return head;
>> }
>>
>> Isn't that equivalent to:
>>
>> int* foo (void) {
>>   int *head;
>>   asm(""::"m"(head):"memory");
>>   return head;
>> }
>>
>> For which neither compiler warns for -Wuninitialized? They would if
>> head was an argument to a function call...
> 
> What's going on here...
> 
> $ cat y.c
> void x (void) {
>  int y;
>  asm(""::"r"(y));
> }
> void z (void) {
>  int y;
>  asm(""::"m"(y));
> }
> $ clang -Wuninitialized y.c -c
> y.c:3:15: warning: variable 'y' is uninitialized when used here
> [-Wuninitialized]
>  asm(""::"r"(y));
>              ^
> y.c:2:8: note: initialize the variable 'y' to silence this warning
>  int y;
>       ^
>        = 0
> 1 warning generated.
> $ gcc -Wuninitialized y.c -c
> y.c: In function ‘x’:
> y.c:3:3: warning: ‘y’ is used uninitialized [-Wuninitialized]
>    3 |   asm(""::"r"(y));
>      |   ^~~
> 
> Only 1 warning each? I expected 2.
> 
> Is there something special about "m" constraints and -Wuninitialized?
> 
> --
> Thanks,
> ~Nick Desaulniers

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

[-- Attachment #2: test-asm.gvn.ll --]
[-- Type: application/octet-stream, Size: 8960 bytes --]

MemorySSA for function: this_cpu_list_pop
; Function Attrs: nounwind uwtable
define dso_local %struct.percpu_list_node* @this_cpu_list_pop(%struct.percpu_list* %0, i32* %1) #0 {
  %3 = alloca %struct.percpu_list_node*, align 8
  %4 = alloca %struct.percpu_list*, align 8
  %5 = alloca i32*, align 8
  %6 = alloca %struct.percpu_list_node*, align 8
  %7 = alloca i64*, align 8
  %8 = alloca i64, align 8
  %9 = alloca i64*, align 8
  %10 = alloca i64, align 8
  %11 = alloca i32, align 4
  %12 = alloca i32, align 4
  %13 = alloca i32, align 4
; 1 = MemoryDef(liveOnEntry)
  store %struct.percpu_list* %0, %struct.percpu_list** %4, align 8, !tbaa !3
; 2 = MemoryDef(1)
  store i32* %1, i32** %5, align 8, !tbaa !3
  br label %14

14:                                               ; preds = %52, %2
; 31 = MemoryPhi({%2,2},{%52,28})
  %15 = phi %struct.percpu_list_node* [ %49, %52 ], [ undef, %2 ]
  %16 = phi i32* [ %51, %52 ], [ %1, %2 ]
  %17 = bitcast %struct.percpu_list_node** %6 to i8*
; 3 = MemoryDef(31)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %17) #5
  %18 = bitcast i64** %7 to i8*
; 4 = MemoryDef(3)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %18) #5
  %19 = bitcast i64* %8 to i8*
; 5 = MemoryDef(4)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %19) #5
  %20 = bitcast i64** %9 to i8*
; 6 = MemoryDef(5)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %20) #5
  %21 = bitcast i64* %10 to i8*
; 7 = MemoryDef(6)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %21) #5
  %22 = bitcast i32* %11 to i8*
; 8 = MemoryDef(7)
  call void @llvm.lifetime.start.p0i8(i64 4, i8* %22) #5
  %23 = bitcast i32* %12 to i8*
; 9 = MemoryDef(8)
  call void @llvm.lifetime.start.p0i8(i64 4, i8* %23) #5
; 10 = MemoryDef(9)
  %24 = call i32 @rseq_cpu_start()
; 11 = MemoryDef(10)
  store i32 %24, i32* %12, align 4, !tbaa !7
  %25 = getelementptr inbounds %struct.percpu_list, %struct.percpu_list* %0, i32 0, i32 0
  %26 = sext i32 %24 to i64
  %27 = getelementptr inbounds [1024 x %struct.percpu_list_entry], [1024 x %struct.percpu_list_entry]* %25, i64 0, i64 %26
  %28 = getelementptr inbounds %struct.percpu_list_entry, %struct.percpu_list_entry* %27, i32 0, i32 0
  %29 = bitcast %struct.percpu_list_node** %28 to i64*
; 12 = MemoryDef(11)
  store i64* %29, i64** %7, align 8, !tbaa !3
; 13 = MemoryDef(12)
  store i64 0, i64* %8, align 8, !tbaa !9
; 14 = MemoryDef(13)
  store i64 8, i64* %10, align 8, !tbaa !9
  %30 = bitcast %struct.percpu_list_node** %6 to i64*
; 15 = MemoryDef(14)
  store i64* %30, i64** %9, align 8, !tbaa !3
; 16 = MemoryDef(15)
  %31 = call i32 @rseq_cmpnev_storeoffp_load(i64* %29, i64 0, i64 8, i64* %30, i32 %24)
; 17 = MemoryDef(16)
  store i32 %31, i32* %11, align 4, !tbaa !7
  %32 = icmp ne i32 %31, 0
  %33 = xor i1 %32, true
  %34 = zext i1 %33 to i32
  %35 = sext i32 %34 to i64
  %36 = call i64 @llvm.expect.i64(i64 %35, i64 1)
  %37 = icmp ne i64 %36, 0
  br i1 %37, label %38, label %44

38:                                               ; preds = %14
  %39 = icmp ne i32* %16, null
  br i1 %39, label %40, label %41

40:                                               ; preds = %38
; 18 = MemoryDef(17)
  store i32 %24, i32* %1, align 4, !tbaa !7
  br label %41

41:                                               ; preds = %40, %38
; 30 = MemoryPhi({%38,17},{%40,18})
  %42 = phi i32* [ %1, %40 ], [ null, %38 ]
; MemoryUse(16) MayAlias
  %43 = load %struct.percpu_list_node*, %struct.percpu_list_node** %6, align 8, !tbaa !3
; 19 = MemoryDef(30)
  store %struct.percpu_list_node* %43, %struct.percpu_list_node** %3, align 8
  br label %48

44:                                               ; preds = %14
  %45 = icmp sgt i32 %31, 0
  br i1 %45, label %46, label %47

46:                                               ; preds = %44
; 20 = MemoryDef(17)
  store %struct.percpu_list_node* null, %struct.percpu_list_node** %3, align 8
  br label %48

47:                                               ; preds = %44
  br label %48

48:                                               ; preds = %47, %46, %41
; 29 = MemoryPhi({%41,19},{%46,20},{%47,17})
  %.sink = phi i32 [ 1, %41 ], [ 1, %46 ], [ 0, %47 ]
  %49 = phi %struct.percpu_list_node* [ %15, %47 ], [ null, %46 ], [ %43, %41 ]
  %50 = phi i32 [ 0, %47 ], [ 1, %46 ], [ 1, %41 ]
  %51 = phi i32* [ %16, %47 ], [ %16, %46 ], [ %42, %41 ]
; 21 = MemoryDef(29)
  store i32 %.sink, i32* %13, align 4
; 22 = MemoryDef(21)
  call void @llvm.lifetime.end.p0i8(i64 4, i8* %23) #5
; 23 = MemoryDef(22)
  call void @llvm.lifetime.end.p0i8(i64 4, i8* %22) #5
; 24 = MemoryDef(23)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %21) #5
; 25 = MemoryDef(24)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %20) #5
; 26 = MemoryDef(25)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %19) #5
; 27 = MemoryDef(26)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %18) #5
; 28 = MemoryDef(27)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %17) #5
  switch i32 %50, label %54 [
    i32 0, label %52
    i32 1, label %53
  ]

52:                                               ; preds = %48
  br label %14

53:                                               ; preds = %48
  ret %struct.percpu_list_node* %49

54:                                               ; preds = %48
  unreachable
}
MemorySSA for function: rseq_cpu_start
; Function Attrs: inlinehint nounwind uwtable
define internal i32 @rseq_cpu_start() #2 {
; 1 = MemoryDef(liveOnEntry)
  %1 = call %struct.rseq* @rseq_get_abi()
  %2 = getelementptr inbounds %struct.rseq, %struct.rseq* %1, i32 0, i32 0
; 2 = MemoryDef(1)
  %3 = load volatile i32, i32* %2, align 32, !tbaa !3
  ret i32 %3
}
MemorySSA for function: rseq_cmpnev_storeoffp_load
; Function Attrs: alwaysinline nounwind uwtable
define internal i32 @rseq_cmpnev_storeoffp_load(i64* %0, i64 %1, i64 %2, i64* %3, i32 %4) #3 {
  %6 = alloca i32, align 4
  %7 = alloca i64*, align 8
  %8 = alloca i64, align 8
  %9 = alloca i64, align 8
  %10 = alloca i64*, align 8
  %11 = alloca i32, align 4
; 1 = MemoryDef(liveOnEntry)
  store i64* %0, i64** %7, align 8, !tbaa !3
; 2 = MemoryDef(1)
  store i64 %1, i64* %8, align 8, !tbaa !7
; 3 = MemoryDef(2)
  store i64 %2, i64* %9, align 8, !tbaa !7
; 4 = MemoryDef(3)
  store i64* %3, i64** %10, align 8, !tbaa !3
; 5 = MemoryDef(4)
  store i32 %4, i32* %11, align 4, !tbaa !9
; 6 = MemoryDef(5)
  %12 = call %struct.rseq* @rseq_get_abi()
; 7 = MemoryDef(6)
  callbr void asm sideeffect ".pushsection __rseq_cs, \22aw\22\0A\09.balign 32\0A\093:\0A\09.long 0x0, 0x0\0A\09.quad 1f, (2f - 1f), 4f\0A\09.popsection\0A\09.pushsection __rseq_cs_ptr_array, \22aw\22\0A\09.quad 3b\0A\09.popsection\0A\09.pushsection __rseq_exit_point_array, \22aw\22\0A\09.quad 1f, ${7:l}\0A\09.popsection\0A\09leaq 3b(%rip), %rax\0A\09movq %rax, 8($1)\0A\091:\0A\09cmpl $0, 4($1)\0A\09jnz 4f\0A\09movq $2, %rbx\0A\09cmpq %rbx, $3\0A\09je ${7:l}\0A\09movq %rbx, $5\0A\09addq $4, %rbx\0A\09movq (%rbx), %rbx\0A\09ud2\0A\09movq %rbx, $2\0A\092:\0A\09.pushsection __rseq_failure, \22ax\22\0A\09.byte 0x0f, 0xb9, 0x3d\0A\09.long 0x53053053\0A\094:\0A\09jmp ${6:l}\0A\09.popsection\0A\09", "r,r,*m,r,er,*m,X,X,~{memory},~{cc},~{rax},~{rbx},~{dirflag},~{fpsr},~{flags}"(i32 %4, %struct.rseq* %12, i64* %0, i64 %1, i64 %2, i64* %3, i8* blockaddress(@rseq_cmpnev_storeoffp_load, %14), i8* blockaddress(@rseq_cmpnev_storeoffp_load, %15)) #5
          to label %13 [label %14, label %15], !srcloc !11

13:                                               ; preds = %5
; 8 = MemoryDef(7)
  call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() #5, !srcloc !12
  br label %16

14:                                               ; preds = %5
  br label %16

15:                                               ; preds = %5
  br label %16

16:                                               ; preds = %15, %14, %13
; 10 = MemoryPhi({%13,8},{%14,7},{%15,7})
  %.sink = phi i32 [ -1, %14 ], [ 1, %15 ], [ 0, %13 ]
  %17 = phi i32 [ 1, %15 ], [ -1, %14 ], [ 0, %13 ]
; 9 = MemoryDef(10)
  store i32 %.sink, i32* %6, align 4
  ret i32 %17
}
MemorySSA for function: rseq_get_abi
; Function Attrs: inlinehint nounwind uwtable
define internal %struct.rseq* @rseq_get_abi() #2 {
; 1 = MemoryDef(liveOnEntry)
  %1 = call i8* @rseq_thread_pointer()
; MemoryUse(1) MayAlias
  %2 = load i32, i32* @rseq_offset, align 4, !tbaa !3
  %3 = sext i32 %2 to i64
  %4 = getelementptr i8, i8* %1, i64 %3
  %5 = bitcast i8* %4 to %struct.rseq*
  ret %struct.rseq* %5
}
MemorySSA for function: rseq_thread_pointer
; Function Attrs: inlinehint nounwind uwtable
define internal i8* @rseq_thread_pointer() #2 {
  %1 = alloca i8*, align 8
  %2 = bitcast i8** %1 to i8*
; 1 = MemoryDef(liveOnEntry)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) #5
  %3 = call i8* asm "mov %fs:0, $0", "=r,~{dirflag},~{fpsr},~{flags}"() #6
; 2 = MemoryDef(1)
  store i8* %3, i8** %1, align 8, !tbaa !3
; 3 = MemoryDef(2)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %2) #5
  ret i8* %3
}

[-- Attachment #3: test.gvn.ll --]
[-- Type: application/octet-stream, Size: 8819 bytes --]

MemorySSA for function: this_cpu_list_pop
; Function Attrs: nounwind uwtable
define dso_local %struct.percpu_list_node* @this_cpu_list_pop(%struct.percpu_list* %0, i32* %1) #0 {
  %3 = alloca %struct.percpu_list_node*, align 8
  %4 = alloca %struct.percpu_list*, align 8
  %5 = alloca i32*, align 8
  %6 = alloca %struct.percpu_list_node*, align 8
  %7 = alloca i64*, align 8
  %8 = alloca i64, align 8
  %9 = alloca i64*, align 8
  %10 = alloca i64, align 8
  %11 = alloca i32, align 4
  %12 = alloca i32, align 4
  %13 = alloca i32, align 4
; 1 = MemoryDef(liveOnEntry)
  store %struct.percpu_list* %0, %struct.percpu_list** %4, align 8, !tbaa !3
; 2 = MemoryDef(1)
  store i32* %1, i32** %5, align 8, !tbaa !3
  br label %14

14:                                               ; preds = %52, %2
; 31 = MemoryPhi({%2,2},{%52,28})
  %15 = phi %struct.percpu_list_node* [ %49, %52 ], [ undef, %2 ]
  %16 = phi i32* [ %51, %52 ], [ %1, %2 ]
  %17 = bitcast %struct.percpu_list_node** %6 to i8*
; 3 = MemoryDef(31)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %17) #5
  %18 = bitcast i64** %7 to i8*
; 4 = MemoryDef(3)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %18) #5
  %19 = bitcast i64* %8 to i8*
; 5 = MemoryDef(4)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %19) #5
  %20 = bitcast i64** %9 to i8*
; 6 = MemoryDef(5)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %20) #5
  %21 = bitcast i64* %10 to i8*
; 7 = MemoryDef(6)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %21) #5
  %22 = bitcast i32* %11 to i8*
; 8 = MemoryDef(7)
  call void @llvm.lifetime.start.p0i8(i64 4, i8* %22) #5
  %23 = bitcast i32* %12 to i8*
; 9 = MemoryDef(8)
  call void @llvm.lifetime.start.p0i8(i64 4, i8* %23) #5
; 10 = MemoryDef(9)
  %24 = call i32 @rseq_cpu_start()
; 11 = MemoryDef(10)
  store i32 %24, i32* %12, align 4, !tbaa !7
  %25 = getelementptr inbounds %struct.percpu_list, %struct.percpu_list* %0, i32 0, i32 0
  %26 = sext i32 %24 to i64
  %27 = getelementptr inbounds [1024 x %struct.percpu_list_entry], [1024 x %struct.percpu_list_entry]* %25, i64 0, i64 %26
  %28 = getelementptr inbounds %struct.percpu_list_entry, %struct.percpu_list_entry* %27, i32 0, i32 0
  %29 = bitcast %struct.percpu_list_node** %28 to i64*
; 12 = MemoryDef(11)
  store i64* %29, i64** %7, align 8, !tbaa !3
; 13 = MemoryDef(12)
  store i64 0, i64* %8, align 8, !tbaa !9
; 14 = MemoryDef(13)
  store i64 8, i64* %10, align 8, !tbaa !9
  %30 = bitcast %struct.percpu_list_node** %6 to i64*
; 15 = MemoryDef(14)
  store i64* %30, i64** %9, align 8, !tbaa !3
; 16 = MemoryDef(15)
  %31 = call i32 @rseq_cmpnev_storeoffp_load(i64* %29, i64 0, i64 8, i64* %30, i32 %24)
; 17 = MemoryDef(16)
  store i32 %31, i32* %11, align 4, !tbaa !7
  %32 = icmp ne i32 %31, 0
  %33 = xor i1 %32, true
  %34 = zext i1 %33 to i32
  %35 = sext i32 %34 to i64
  %36 = call i64 @llvm.expect.i64(i64 %35, i64 1)
  %37 = icmp ne i64 %36, 0
  br i1 %37, label %38, label %44

38:                                               ; preds = %14
  %39 = icmp ne i32* %16, null
  br i1 %39, label %40, label %41

40:                                               ; preds = %38
; 18 = MemoryDef(17)
  store i32 %24, i32* %1, align 4, !tbaa !7
  br label %41

41:                                               ; preds = %40, %38
; 30 = MemoryPhi({%38,17},{%40,18})
  %42 = phi i32* [ %1, %40 ], [ null, %38 ]
; MemoryUse(16) MayAlias
  %43 = load %struct.percpu_list_node*, %struct.percpu_list_node** %6, align 8, !tbaa !3
; 19 = MemoryDef(30)
  store %struct.percpu_list_node* %43, %struct.percpu_list_node** %3, align 8
  br label %48

44:                                               ; preds = %14
  %45 = icmp sgt i32 %31, 0
  br i1 %45, label %46, label %47

46:                                               ; preds = %44
; 20 = MemoryDef(17)
  store %struct.percpu_list_node* null, %struct.percpu_list_node** %3, align 8
  br label %48

47:                                               ; preds = %44
  br label %48

48:                                               ; preds = %47, %46, %41
; 29 = MemoryPhi({%41,19},{%46,20},{%47,17})
  %.sink = phi i32 [ 1, %41 ], [ 1, %46 ], [ 0, %47 ]
  %49 = phi %struct.percpu_list_node* [ %15, %47 ], [ null, %46 ], [ %43, %41 ]
  %50 = phi i32 [ 0, %47 ], [ 1, %46 ], [ 1, %41 ]
  %51 = phi i32* [ %16, %47 ], [ %16, %46 ], [ %42, %41 ]
; 21 = MemoryDef(29)
  store i32 %.sink, i32* %13, align 4
; 22 = MemoryDef(21)
  call void @llvm.lifetime.end.p0i8(i64 4, i8* %23) #5
; 23 = MemoryDef(22)
  call void @llvm.lifetime.end.p0i8(i64 4, i8* %22) #5
; 24 = MemoryDef(23)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %21) #5
; 25 = MemoryDef(24)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %20) #5
; 26 = MemoryDef(25)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %19) #5
; 27 = MemoryDef(26)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %18) #5
; 28 = MemoryDef(27)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %17) #5
  switch i32 %50, label %54 [
    i32 0, label %52
    i32 1, label %53
  ]

52:                                               ; preds = %48
  br label %14

53:                                               ; preds = %48
  ret %struct.percpu_list_node* %49

54:                                               ; preds = %48
  unreachable
}
MemorySSA for function: rseq_cpu_start
; Function Attrs: inlinehint nounwind uwtable
define internal i32 @rseq_cpu_start() #2 {
; 1 = MemoryDef(liveOnEntry)
  %1 = call %struct.rseq* @rseq_get_abi()
  %2 = getelementptr inbounds %struct.rseq, %struct.rseq* %1, i32 0, i32 0
; 2 = MemoryDef(1)
  %3 = load volatile i32, i32* %2, align 32, !tbaa !3
  ret i32 %3
}
MemorySSA for function: rseq_cmpnev_storeoffp_load
; Function Attrs: alwaysinline nounwind uwtable
define internal i32 @rseq_cmpnev_storeoffp_load(i64* %0, i64 %1, i64 %2, i64* %3, i32 %4) #3 {
  %6 = alloca i32, align 4
  %7 = alloca i64*, align 8
  %8 = alloca i64, align 8
  %9 = alloca i64, align 8
  %10 = alloca i64*, align 8
  %11 = alloca i32, align 4
; 1 = MemoryDef(liveOnEntry)
  store i64* %0, i64** %7, align 8, !tbaa !3
; 2 = MemoryDef(1)
  store i64 %1, i64* %8, align 8, !tbaa !7
; 3 = MemoryDef(2)
  store i64 %2, i64* %9, align 8, !tbaa !7
; 4 = MemoryDef(3)
  store i64* %3, i64** %10, align 8, !tbaa !3
; 5 = MemoryDef(4)
  store i32 %4, i32* %11, align 4, !tbaa !9
; 6 = MemoryDef(5)
  %12 = call %struct.rseq* @rseq_get_abi()
; 7 = MemoryDef(6)
  callbr void asm sideeffect ".pushsection __rseq_cs, \22aw\22\0A\09.balign 32\0A\093:\0A\09.long 0x0, 0x0\0A\09.quad 1f, (2f - 1f), 4f\0A\09.popsection\0A\09.pushsection __rseq_cs_ptr_array, \22aw\22\0A\09.quad 3b\0A\09.popsection\0A\09.pushsection __rseq_exit_point_array, \22aw\22\0A\09.quad 1f, ${7:l}\0A\09.popsection\0A\09leaq 3b(%rip), %rax\0A\09movq %rax, 8($1)\0A\091:\0A\09cmpl $0, 4($1)\0A\09jnz 4f\0A\09movq $2, %rbx\0A\09cmpq %rbx, $3\0A\09je ${7:l}\0A\09movq %rbx, $5\0A\09addq $4, %rbx\0A\09movq (%rbx), %rbx\0A\09ud2\0A\09movq %rbx, $2\0A\092:\0A\09.pushsection __rseq_failure, \22ax\22\0A\09.byte 0x0f, 0xb9, 0x3d\0A\09.long 0x53053053\0A\094:\0A\09jmp ${6:l}\0A\09.popsection\0A\09", "r,r,*m,r,er,*m,X,X,~{memory},~{cc},~{rax},~{rbx},~{dirflag},~{fpsr},~{flags}"(i32 %4, %struct.rseq* %12, i64* %0, i64 %1, i64 %2, i64* %3, i8* blockaddress(@rseq_cmpnev_storeoffp_load, %14), i8* blockaddress(@rseq_cmpnev_storeoffp_load, %15)) #5
          to label %13 [label %14, label %15], !srcloc !11

13:                                               ; preds = %5
  br label %16

14:                                               ; preds = %5
  br label %16

15:                                               ; preds = %5
  br label %16

16:                                               ; preds = %15, %14, %13
  %.sink = phi i32 [ -1, %14 ], [ 1, %15 ], [ 0, %13 ]
  %17 = phi i32 [ 1, %15 ], [ -1, %14 ], [ 0, %13 ]
; 8 = MemoryDef(7)
  store i32 %.sink, i32* %6, align 4
  ret i32 %17
}
MemorySSA for function: rseq_get_abi
; Function Attrs: inlinehint nounwind uwtable
define internal %struct.rseq* @rseq_get_abi() #2 {
; 1 = MemoryDef(liveOnEntry)
  %1 = call i8* @rseq_thread_pointer()
; MemoryUse(1) MayAlias
  %2 = load i32, i32* @rseq_offset, align 4, !tbaa !3
  %3 = sext i32 %2 to i64
  %4 = getelementptr i8, i8* %1, i64 %3
  %5 = bitcast i8* %4 to %struct.rseq*
  ret %struct.rseq* %5
}
MemorySSA for function: rseq_thread_pointer
; Function Attrs: inlinehint nounwind uwtable
define internal i8* @rseq_thread_pointer() #2 {
  %1 = alloca i8*, align 8
  %2 = bitcast i8** %1 to i8*
; 1 = MemoryDef(liveOnEntry)
  call void @llvm.lifetime.start.p0i8(i64 8, i8* %2) #5
  %3 = call i8* asm "mov %fs:0, $0", "=r,~{dirflag},~{fpsr},~{flags}"() #6
; 2 = MemoryDef(1)
  store i8* %3, i8** %1, align 8, !tbaa !3
; 3 = MemoryDef(2)
  call void @llvm.lifetime.end.p0i8(i64 8, i8* %2) #5
  ret i8* %3
}

  parent reply	other threads:[~2021-12-16 16:39 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <157245708.33559.1639605989199.JavaMail.zimbra@efficios.com>
2021-12-15 23:50 ` clang asm goto issue small reproducer Nick Desaulniers
2021-12-16  0:18   ` Nick Desaulniers
2021-12-16  0:25     ` Nick Desaulniers
2021-12-16  0:29       ` Mathieu Desnoyers
2021-12-16 16:39       ` Mathieu Desnoyers [this message]
2021-12-16  0:26     ` Mathieu Desnoyers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1302544343.35446.1639672770172.JavaMail.zimbra@efficios.com \
    --to=mathieu.desnoyers@efficios.com \
    --cc=efriedma@quicinc.com \
    --cc=jyknight@google.com \
    --cc=llvm@lists.linux.dev \
    --cc=morbo@google.com \
    --cc=ndesaulniers@google.com \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox