<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/126252>126252</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[StackColoring] WRONG code
</td>
</tr>
<tr>
<th>Labels</th>
<td>
llvm:codegen
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
JonPsson1
</td>
</tr>
</table>
<pre>
It seems that StackColoring marks a stack slot as dead even though it has its address taken and used.
The test case has enclosing braces and fails at -Os, but if I remove the braces the problem disapears:
wrong0.i: <> with braces removed
```
int printf(const char *, ...); int printf(const char *, ...);
char GlobCh0 = 0, Res = 0, GlobCh1 = 0; char GlobCh0 = 0, Res = 0, GlobCh1 = 0;
int b = 0, g = 0; int b = 0, g = 0;
int *GlobIntPtr = 0; int *GlobIntPtr = 0;
long e = 0; long e = 0;
void fun(int FunArg) { void fun(int FunArg) {
char *FunPtr = &Res; char *FunPtr = &Res;
*FunPtr = FunArg; *FunPtr = FunArg;
} }
int main() { int main() {
{ |
int MainInt0 = 0, MainInt1 = 0; int MainInt0 = 0, MainInt1 = 0;
GlobCh1 = GlobCh0 + 1; GlobCh1 = GlobCh0 + 1;
for (; b <= 0; b = GlobCh1) { for (; b <= 0; b = GlobCh1) {
int *m = 0; int *m = 0;
int **o = &m; int **o = &m;
int ***n[7]; int ***n[7];
n[g] = &o; n[g] = &o;
fun(((void*) (GlobIntPtr = &MainInt0)) fun(((void*) (GlobIntPtr = &MainInt0))
} }
int p[7]; int p[7];
for (; MainInt1 < 7; MainInt1++) for (; MainInt1 < 7; MainInt1++)
p[MainInt1] = 9; p[MainInt1] = 9;
e = p[4]; e = p[4];
} |
printf("%d\n", Res); printf("%d\n", Res);
} }
```
clang -march=z15 -Os wrong0.i -o a.out
The generated IRs are identical, except for the lifetime.end intrinsics at the end:
```
for.end14: ; preds = % for.end14: ; preds = %
%arrayidx15 = getelementptr inbounds nuw i8, ptr %p, i64 16 %arrayidx15 = getelementptr inbounds nuw i8, ptr %p, i64 16
%3 = load i32, ptr %arrayidx15, align 4, !tbaa !7 %3 = load i32, ptr %arrayidx15, align 4, !tbaa !7
%conv16 = sext i32 %3 to i64 %conv16 = sext i32 %3 to i64
store i64 %conv16, ptr @e, align 8, !tbaa !19 store i64 %conv16, ptr @e, align 8, !tbaa !19
call void @llvm.lifetime.end.p0(i64 28, ptr nonnull %p) #4 <
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %MainInt0 <
%4 = load i8, ptr @Res, align 2, !tbaa !4 %4 = load i8, ptr @Res, align 2, !tbaa !4
%conv17 = zext i8 %4 to i32 %conv17 = zext i8 %4 to i32
%call = call signext i32 (ptr, ...) @printf(ptr noundef non %call = call signext i32 (ptr, ...) @printf(ptr noundef non
> call void @llvm.lifetime.end.p0(i64 28, ptr nonnull %p) #4
> call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %MainInt0
ret i32 0 ret i32 0
```
This difference causes DSEPass to remove the initialization of MainInt0 with the reduced lifetime:
```
; *** IR Dump After DSEPass on main *** ; *** IR Dump After DSEPass on main ***
; Function Attrs: nounwind optsize ; Function Attrs: nounwind optsize
define dso_local signext i32 @main() local_unnamed_addr #2 { define dso_local signext i32 @main() local_unnamed_addr #2 {
entry: entry:
%MainInt0 = alloca i32, align 4 %MainInt0 = alloca i32, align 4
%m = alloca ptr, align 8 %m = alloca ptr, align 8
%o = alloca ptr, align 8 %o = alloca ptr, align 8
%n = alloca [7 x ptr], align 8 %n = alloca [7 x ptr], align 8
%p = alloca [7 x i32], align 4 %p = alloca [7 x i32], align 4
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %MainInt0) #4 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %MainInt0) #4
> store i32 0, ptr %MainInt0, align 4, !tbaa !7
%0 = load i8, ptr @GlobCh0, align 2, !tbaa !4 %0 = load i8, ptr @GlobCh0, align 2, !tbaa !4
%add = add i8 %0, 1 %add = add i8 %0, 1
```
This is ok, as the only use of MainInt0 is to compare its address to another:
```
for.cond.for.end_crit_edge: ; preds = %for.bod for.cond.for.end_crit_edge: ; preds = %for.bod
%conv6 = zext i8 %add to i32 %conv6 = zext i8 %add to i32
%cmp4 = icmp ne ptr %MainInt0, %2 %cmp4 = icmp ne ptr %MainInt0, %2
%conv.i = zext i1 %cmp4 to i8 %conv.i = zext i1 %cmp4 to i8
store ptr %MainInt0, ptr @GlobIntPtr, align 8, !tbaa !14 store ptr %MainInt0, ptr @GlobIntPtr, align 8, !tbaa !14
store i8 %conv.i, ptr @Res, align 1, !tbaa !4 store i8 %conv.i, ptr @Res, align 1, !tbaa !4
store i32 %conv6, ptr @b, align 4, !tbaa !7 store i32 %conv6, ptr @b, align 4, !tbaa !7
br label %for.end br label %for.end
```
It then seems to me that this leads to problems with StackColoring, which marks the stack slot as dead and seemingly just replaces the use of it with another one, which can't be good:
```
# *** IR Dump After Merge disjoint stack slots (stack-coloring) ***: # *** IR Dump After Merge disjoint stack slots (stack-coloring) ***:
# Machine code for function main: IsSSA, TracksLiveness # Machine code for function main: IsSSA, TracksLiveness
Frame Objects: Frame Objects:
fi#0: dead | fi#0: size=4, align=4, at location [SP]
fi#1: size=8, align=8, at location [SP] fi#1: size=8, align=8, at location [SP]
fi#2: size=56, align=8, at location [SP] fi#2: size=56, align=8, at location [SP]
...
bb.2.for.body: bb.2.for.body:
; predecessors: %bb.1, %bb.2 ; predecessors: %bb.1, %bb.2
successors: %bb.2(0x7c000000), %bb.3(0x04000000); %bb.2(96.88%), % successors: %bb.2(0x7c000000), %bb.3(0x04000000); %bb.2(96.88%), %
%15:gr64bit = LA %stack.1.o, 0, $noreg %15:gr64bit = LA %stack.1.o, 0, $noreg
STG killed %15:gr64bit, %1:addr64bit, 0, $noreg :: (store (s64) in STG killed %15:gr64bit, %1:addr64bit, 0, $noreg :: (store (s64) in
%2:gr64bit = LG %stack.2.n, 0, $noreg :: (dereferenceable load (s6 %2:gr64bit = LG %stack.2.n, 0, $noreg :: (dereferenceable load (s6
TMLMux %0:grx32bit, 255, implicit-def $cc TMLMux %0:grx32bit, 255, implicit-def $cc
BRC 15, 8, %bb.2, implicit $cc BRC 15, 8, %bb.2, implicit $cc
J %bb.3 J %bb.3
bb.3.for.cond.for.end_crit_edge: bb.3.for.cond.for.end_crit_edge:
; predecessors: %bb.2 ; predecessors: %bb.2
successors: %bb.4(0x80000000); %bb.4(100.00%) successors: %bb.4(0x80000000); %bb.4(100.00%)
%16:gr32bit = LLCRMux %0:grx32bit %16:gr32bit = LLCRMux %0:grx32bit
%17:gr64bit = LA %stack.1.o, 0, $noreg | %17:gr64bit = LA %stack.0.MainInt0, 0, $noreg
CGR %17:gr64bit, %2:gr64bit, implicit-def $cc CGR %17:gr64bit, %2:gr64bit, implicit-def $cc
```
It seems FI#0 should not be marked dead as there is a use of it, even just for comparing the final address with another.
@mohammed-nurulhoque @kazutakahirata @nikic @uweigand
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy0Wl9vnLoS_zTOyygIDOyfhzxsdk-qHLX3VGml-1gZ7GV9AvZebJK0n_5qbGDZvyFJiyLFsWd-M7bH499AmDGyUELckPSWpKsr1tiNrm_-1uqrMVpFV5nmP2_uLRghKgN2wyx8syx_XOpS11IVULH60QADg71gSm2BGeCCcRBPQoHd6KbYgLSwYQakNcA4r4UxYNmjUMAUh8YIHpBwQcLF940AK4yFnBnhVITKS23QVFazXBinsWayNMAsXP9jCF1C1liQa7iHWlT6SYDdiE4cm9taZ6WogEvDtoLVhsQLb--51qoIA0niBQCJlyT-C56l3XTaHo97YTIJ259wIZWFbS2VXRM6y7VClzesBkIX6FAQBITOSXwLR89YTRIuXP-nUmfLTQgkXkGIEg_C7P7wo1HbEd_CO3Ta6WQ7iWKHd3ak1SJ0gXj3yn619b7a6SESLkqtChA74THPgY7fkSctOawbRegMDd41alEXhM6BTC-gXtIi4QL6_bhrVOc5oZMHYV5x9pIeAu8PtXZfnf8ZLVyB6QrIdOXXAqdSMYmz6lbguMtN7-LiHJufLlELsb4wqe6VHcRV2xOd38uRes4x2AvNPojpLUQXl-mSVgu81rgzM4TJ_EFv_c0GWtH50HmTfmsTulNQvS3Uj7QO8Qhd6C66qnGoZzS7nfVDhC4USW-nJF2N9PWcbu8x9hUkXXVG9dhFOKnZw_rT63_wODsH5rhDBxmH0EkXfZhW6Xxn4AMY7jBPV-Mm0j_-qHbLth2s9MHfxzE7OC9LmA57CL11P_M3ivdLiXb70Xa53c11bqDV9LkYhZJ2Fkc9bbZ5yzq12aa_IAmlhKacpEvlmu4qO3e17p4x-ocJdHi94-VbMlXAdcXqfEPi1a8oRbYBHWOAaw0s0I3dEZdCKFEzKzjcPxhgtQDJhbIyZyUaFi-52Fq3TUhKSrkWVlYiEIpjANRSGZk7VoPDQvGepQw9W-saNaIEKYvbplpw08Zp6qPmgoDfEpqyumY_JX-JUjdSCCtKUQllt7YGqTLdKG5ANc8gZ-g8dhOabrEtJwlEk9-D0vkTO4BSMw4ypgPZnQnsZKUsFCTYJDSyGWP4e3oYRB_F67zKtXrCmcYrMOLFIpQHt9r5_7qIQzJWYzAMFXqPklDsHJkdOBLNT8T2B9A8u2Fl6TkQScKyfKqCYSgG2xB50SQB2m-Z0ko1ZdluHabIOPF0OVyMhktOoA2IwbJb82Swc7PBxNy57aZGD6aWnEsn78Xbi4Cpg_jltnfmMXF3_U5fluhxcJVQxjVc1dUHy2xr6x31R9_69OXXq1FcrHHdujn9HrT-Cnjvg9XS74kmd6HGf8H46LwUTm5itfArEu5ax0n--0Ya4HK9FrVQuYCcNUYYWH376yvDGlUPK0qppJWslL-YlVqBXu-IrasZUaYWvMkF77P7yRyOWblnTXD_AKum2sJibUXdm9bKUfeB3Lu0Wmt3jcqd0wtrXfnr4uBZKg56a438Jcbu-BgsEi64WEslgBv9o9Q5OwjSJByUJW78R6MUqwT_wTjHPI1S-0T89yCScCGUrX-i212jO6N7ZQorEaW7PNp7YpxUh1cNRdpT2WbmV4Y7BH0B4a1n9SJaZ1ANRZCQwouTTFcHzo8S7FC3J4RxyYbCyWjB1y4xY1ltRyaK_jKDy6nnHZi7lNbd2C4F7ZjITuFVHhKeucPaYvfSvfghbf_SImWc-43hvL3enFL01hjsAvEc3pn8LA3oR-elf52nVfkTGiP2MrB02TrX1dYR7-GLRg1MabsR9VlCnWvFg5Y4_8hraX8IXoiTBBqlMs2hZdrnNc_M_gzekG9MDskErtM-4bgg0iNVW099ZF5tQYlTYUdoSsdv21jENmrQz0AOHI16EPR0NkZmQJ9PGBvEsS_XL3DfI4b4e1CH_H4wo3M8Mzo6nx_QHdoehMZAPxtfM51anHegOp-yGkqWibKLb6xwT_Qdn8V7V_uq7nODhkr4jw4W80ApGHe97ft842nX3gcJ9Od5I_NN-2UC88WJbxNMcWdEqqL8Cf82xkIttmX_xaDNLtJ6E23-AK3EzkDOFKFTC5mAQuvT1Tqh8VnO9kXUhQAuzb9aKjvw0iCLd39e5_205gNO57PLn8Ju3f7C8g0Srlxz4V5arDve55hWvIB78-2b-2bxvWb5o_ksn4TChPshbRIu7mpWCfgn-1fk1vHLww4XZGtJaBzisNvR9z5kusRfOzRHYONV0gd5_4d1xNJNgqS3374iLek9iQa6s6Hu7Jzue_XQplOlA9V0Ms7mK897cX3ku5rTtbIsoEF7tTmufdjR1iV4FYpcGKN9JUFommVBm-mwOfZ68ns5CtGnzSY_EqKEzsKXaR66x73q7ZRiNxQmuyFXjHVa80kwmxGa7nS8Q3_aSrvs2IxSEi-KepJk0rr79LMz6I56EAUaNdobOlG6FsW7lJy1b98_waMsS8EPMVq3MKaRffV9B4bjhV-Omb9msDFJMA1J_4bjj1roFoweTv3Tbuo0UJdAuahF-8aAZaXw1NrZaOPwD6E7179_-fylefGkGW28xLRdA5q6d5qy2pYyl_aaizXi5_krx-YdiM6T24cl-Neos-HxGii05scKOtS_u8Owa_U5JQ4uc-7XRS7mHXohg5xPG4k7tbPwxKnFoSgMA-xO9z4-HT0fRB5mgonbRbeJPvY-Lx9ObPBbZFtKH03fmmQupuvp8lXQMBhS8-NctPz0cIjRlyF7PW86FR9APUlqPZ-9u0eOAWajm5KD0o46Ik0VvGWljnwi8TbAdhzUfTx6EsrzVCRTvsyVqnBkdS0VK_tyd0hY29uYJGGlN6yqBL9WTd2UG_2_RiCVf2S_Gsse2UbWzDLsUfJR5thonoUskCdf8ZuYz-M5uxI30TSezZMonUZXm5uI0imd0Gw6CaMpT-brJApFxqJ4xvMoX2dX8oaGNA1pOI3SaB5HQcgnk4zFSTyjE55RTpJQVEyWgXvbouviShrTiJuITmhKr1zBYNw_J1GKIiReIKEshPuYl66u6hvsvs6awpAkLKWxZodlpS3dvzbtVwjIgv778M9_PjlyetXU5c3G2q0jlvSO0LtC2k2TBbmuCL1zZv2v622tkYISeufcNITetZ4-3dD_BwAA___7oB8q">