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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.