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
}
next prev 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