<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/60732>60732</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
SROA does not propagate function attributes when replacing an indirect call
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
DavidSpickett
</td>
</tr>
</table>
<pre>
This is best demonstrated on AArch64 but the issue applies to any function attribute.
In this example we have `setjmp`, which is a `returns_twice` function (once when you setup the jump, once when you use it later). On AArch64 we want to place a branch target ID instruction after calls to `setjmp`, in case the implementation jumps there in a specific way.
```
extern int __attribute__((returns_twice)) setjmp(void*);
void bbb(void) {
setjmp(0);
int (*fnptr)(void*) = setjmp;
fnptr(0);
}
```
The example has a direct call to setjmp and an indirect call to setjmp. The latter is rather unlikely to ever happen, but this issue applies to all function attributes so I'm using it to demonstrate.
Compile it with:
```
$ ./bin/clang /tmp/test.c -o - -S -mbranch-protection=bti -O1
```
What I expect to happen is:
* The indirect call is converted into a direct call by SROA
* Since both calls are to a returns twice function, both should have a branch target ID instruction placed after them.
What happens is that only the first call is followed by a bti:
```
.cfi_offset w29, -16
mov x0, xzr
bl setjmp
hint #36
mov x0, xzr
bl setjmp
```
GCC gets this right and both have a bti.
```
mov x0, 0
bl setjmp
hint 36 // bti j
mov x0, 0
bl setjmp
hint 36 // bti j
```
(bti is actually encoded as a hint instruction hence the hint mnemonic)
This is the IR:
```
$ ./bin/clang /tmp/test.c -o - -S -mbranch-protection=bti -O1 -emit-llvm
define dso_local void @bbb() local_unnamed_addr #0 {
entry:
%call = call i32 @setjmp(ptr noundef null) #2
%call1 = call i32 @setjmp(ptr noundef null) #3
ret void
}
declare i32 @setjmp(ptr noundef) local_unnamed_addr #1
attributes #0 = { nounwind uwtable "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+fp-armv8,+neon,+outline-atomics,+v8a,-fmv" }
attributes #1 = { returns_twice "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+fp-armv8,+neon,+outline-atomics,+v8a,-fmv" }
attributes #2 = { nounwind returns_twice }
attributes #3 = { nounwind }
```
You can see that the direct call is tagged returns twice and the converted indirect call is not.
IR before and after SROA:
```
$ ./bin/clang /tmp/test.c -o - -S -mbranch-protection=bti -O1 -emit-llvm -mllvm --print-before-all -mllvm --print-after-all 2>&1 | less
*** IR Dump Before SROAPass on bbb ***
; Function Attrs: nounwind uwtable
define dso_local void @bbb() #0 {
entry:
%fnptr = alloca ptr, align 8
%call = call i32 @setjmp(ptr noundef null) #3
call void @llvm.lifetime.start.p0(i64 8, ptr %fnptr) #4
store ptr @setjmp, ptr %fnptr, align 8, !tbaa !7
%0 = load ptr, ptr %fnptr, align 8, !tbaa !7
%call1 = call i32 %0(ptr noundef null)
call void @llvm.lifetime.end.p0(i64 8, ptr %fnptr) #4
ret void
}
*** IR Dump After SROAPass on bbb ***
; Function Attrs: nounwind uwtable
define dso_local void @bbb() #0 {
entry:
%call = call i32 @setjmp(ptr noundef null) #3
%call1 = call i32 @setjmp(ptr noundef null)
ret void
}
```
Prior to SROA the indirect call has no attributes. This is correct as there is no way from C to add them, and in any case, we didn't attempt to.
However, when SROA replaces the indirect call, it knows what its replacing it with. So it seems like it could carry the attributes forward into the new direct call.
I've used AArch64 BTI protection to demonstrate but the same applies to any function attribute.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWE9v2zzS_zT0ZSDDphz_OfiQ2G_ezakP2gKLPQWUNLLYUqRAjuz4-fSLoRTZcpKn7Ra72MMWRhWJw-HMjzO_4VCFoA8WcSvuHsTdfqJaqpzf7tVRF18anX9HoknmivP2a6UD6AAZBoICa2cDeUVYgLNwf-_zarmArCWgCkGH0CKopjEaA5ADZc9QtjYn7SwoIq-zlnAqZnsxu-_-f7JAvAa-qLoxCCeESh0RxHIWkL7VjVjOhNzBqdJ5xZYoHvJIrbfhmU46R7GcXVYRcu1sjnCq0MLZtRCQ2iaa962tG1Y1Hm8DgiYwitALuZnCp4tjJ4STssSuNEblCAoyr2xeASl_QIKnPWhGpO1dLAk95MqY6P6tD9pCrgJ2WLG3NVpScSbbFnjAI4spCA3mutQ5nNR5BBjr6n7xFV8IvQVtCZ6fB4ifn4VcC7ke4yQ3Qm6gN0muj04XQt7z5_ThegkegCzLBpkNiFUvAZf5s-uZEE2Iq96XtiEfV7taA0S6f517mdSLjnWJ1f5dX79WOMRJpTgUCu0xp4g4A96pB2ULUIzJu8NTYD1GEe-VDuAVww6tNfo7mjML4hE9VKpp0PK-dfEdE-E2wI15J8ADBAdPQq5qaIO2B44vctfpM9rRnasbbWIUnjRVIn1_p4VcwFTIx0xbIR9zo-wBhHwk3otHwkDTHBIHCSRfIKm7OE0a7wijeSLdZ6Qh-TR_V_vfK0XwBPjSMGLkevdBh4s98j5CN8ZVB8idPaJnUtCWQRltS3aGL58_Xan4ojn_MkdVnynKY8QS-miFGK0DrnEHWDpUrjVFRw8_SMSYrUWfj1RhPQI8-tr5F8mN-N1Z3vsKodQ-XHwrnTHuhAX7oSAj_dH2QP9vmpf62ZVlQIIT58AOkvlyLFO7Y3y-RFp4-dOPhzPTPftsGY1VXZql6e-rvHHg_3c7OCCFLtS9PlQUMyli_wo66elfej82Y_bGiA9dAoB0yfEs5CMvA99-RvEPkfpI7ZvcWvMgl5ecWmXMGdDmruAYYp6Juq4DrEIOYg6XOFRbzm2dM4tdBdpr9WS5p8__9sSGBGtNiTHHutNcYKktQhHcs3G5MhCZXSxmHbkzK8fvz621qsbiWRWF5-iaXQgfLfnzYDqAkHcxN5jOuyRJJascykJDHqxrbYEl2NaYyP0ylTcK5r-sIX3V4JGiJ7fVovc5N8wof6H0Y7_n15qu-LyDJN0zLFHLSdsC2hOpzCAIKUuvakwap208RkiR7oWU1tnEoCqFlBBfE_KqabQ9JLWiapAj32IvE0jl31931_kka8sSfRL0nziIr3vZjvuSvGmHoQNa9ByH1wIlKmo9hkFKyIeySZSvj2shd0I-WIw8K-SDa8loi4kiV-s8dB-PayXkLinrY1T8CvgYoPkA0OjU8T90IjrybfjcwPT-vPTtvI-OR_9wLeTKQkDsShrTzk2pJnU4YHFTaZnlWfa6jt_Ms47Gx_bPkGHpfDe5q7OxzP8HOQ6SunskjdeWks6ghC2-GYn2xQEp0v8TcjkHsdqBwRCGc0n3g6fPsG_rBh4679inP1QI3O5kWQaDYD8vfYDH1_PfPZHn09IbgvhpMv4h88bjcowIZVgJxNPzDpTRBwvr3-XogWHjpFf7GMqp0SWSrnEaSHmaNjMh13q5AE4RiEb11vWqFkO7QIxjlLgYcDvl4oHcgZBzypTi5-rKo46AjVPFq9e_ruO9wiPvZu8j8hNgoC1-AYqP6tab4Lsf8um_KPZ-L6L-par_I-DGHPOH185zJ8HAdU32iMa4ZbTuqk3jTrA7oOXORzk19OBR9KTOUHpXwy42KEWkyTqGmi1in27PsaWPNxRMtoUVckW8BtYN91Ej1vybO3Fr2d1noO0M9Ri7lfDW4nhnQPDdulOAEzO6ptDL920lN4xT-OL474BYB-Ault_y2CzlyvuurbkqK6XzJ-X7bo3HLJ6uC8WY6YVcHRHagMVwL_Lw9Qku5HzT2w7XQUHVP3MbNCm2abFJN2qC2_lytUyXm3W6mFTb9VphucrKTG5UXqQZqk22kOldWWzW5XKOE72VM5nO5Hwxn81X88V0tck25R1mRb65y2ezjVjMsFbaTGPWOn-YxA5-u5ytUjkxKkMT4h2YlAxBHOQDwN1-4rc8J8naQ-Cs14HCRQtpMriNu1c4jNWR8WjUgf1_70Igbvdl525vJyatN9uKqIndduxWDpqqNpvmrhbyMR7puwdXxW-Yk5CP0d4g5GP0558BAAD__1NGF8g">