<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/99265>99265</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
High stack usage in Linux kernel's drivers/gpu/drm/omapdrm/dss/dispc.c
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
nathanchance
</td>
</tr>
</table>
<pre>
Our continuous integration noticed two new instances of `-Wframe-larger-than` when building for `ARCH=loongarch` although it does not appear to be LoongArch specific after reducing the file down with `cvise`.
```c
typedef short __u16;
typedef int __u32;
typedef __u16 u16;
typedef __u32 u32;
enum { true } typedef bool;
void _dev_printk(char);
struct device {
struct device_node *of_node;
};
void *dev_get_drvdata(struct device *);
u32 __raw_readl(void *addr) { return *(u32 *)addr; }
void __raw_writel(u32 value, void *addr) { *(u32 *)addr = value; }
struct seq_file {
void *private;
} seq_printf(struct seq_file *, ...);
bool of_property_read_bool(struct device_node *, char *);
struct platform_device {
struct device dev;
} pm_runtime_disable(struct device *);
struct soc_device_attribute {};
enum omap_plane_id {
OMAP_DSS_GFX,
OMAP_DSS_VIDEO1,
OMAP_DSS_VIDEO2,
OMAP_DSS_VIDEO3,
OMAP_DSS_WB
};
struct dss_device *dss_debugfs_create_file(struct dss_device *, char *, int(),
void *);
u16 DISPC_OVL_BASE(enum omap_plane_id plane) {
switch (plane) {
case OMAP_DSS_GFX:
return 128;
case OMAP_DSS_VIDEO1:
return 188;
case OMAP_DSS_VIDEO2:
return 76;
case OMAP_DSS_VIDEO3:
return 300;
case OMAP_DSS_WB:
return 0;
}
__builtin_unreachable();
}
u16 DISPC_ACCU2_0_OFFSET(enum omap_plane_id plane) {
switch (plane) {
case OMAP_DSS_VIDEO1:
return 84;
default:
__builtin_unreachable();
}
}
u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane_id plane, u16 i) {
switch (plane) {
case OMAP_DSS_VIDEO1:
return i * 8;
default:
__builtin_unreachable();
}
}
u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane_id plane, u16 i) {
switch (plane) {
case OMAP_DSS_VIDEO1:
return 1424 + i * 8;
default:
__builtin_unreachable();
}
}
u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane_id plane, u16 i) {
switch (plane) {
case OMAP_DSS_WB:
return 224 + i * 4;
default:
__builtin_unreachable();
}
}
struct dispc_device {
struct dss_device *dss;
long core_clk_rate;
long tv_pclk_rate;
u32 ctx[1024];
u32 *gamma_table[4];
struct dispc_features *feat;
};
void dispc_write_reg(struct dispc_device *dispc, u16 idx, u32 val) {
__raw_writel(val, dispc + idx);
}
u32 dispc_read_reg(struct dispc_device *dispc, u16 idx) {
return __raw_readl(dispc + idx);
}
static void dispc_save_context(struct dispc_device *dispc) {
int i, j;
for (i = 0;; i++) {
for (j = 0; j; j++)
;
{
for (; j < 8; j++)
dispc->ctx[DISPC_OVL_BASE(i) + j] = dispc_read_reg(
dispc, DISPC_OVL_BASE(i) + DISPC_FIR_COEF_H2_OFFSET(i, j));
for (j = 0; j < 8; j++)
dispc->ctx[DISPC_OVL_BASE(i) + DISPC_FIR_COEF_HV2_OFFSET(i, j)] =
dispc_read_reg(dispc, i + DISPC_FIR_COEF_HV2_OFFSET(i, j));
for (j = 0; j < 8; j++)
dispc->ctx[DISPC_OVL_BASE(i) + DISPC_FIR_COEF_V2_OFFSET(i, j)] =
dispc_read_reg(dispc, i + DISPC_FIR_COEF_V2_OFFSET(i, j));
}
}
}
static void dispc_restore_context(struct dispc_device *dispc) {
int i, j;
for (i = 0;; i++) {
for (j = 0; j; j++)
;
{
dispc_write_reg(dispc, 0,
dispc->ctx[DISPC_OVL_BASE(i) + DISPC_ACCU2_0_OFFSET(i)]);
dispc_write_reg(dispc, i, dispc->ctx[DISPC_OVL_BASE(i)]);
for (; j < 8; j++)
dispc_write_reg(dispc, i + DISPC_FIR_COEF_H2_OFFSET(i, j),
dispc->ctx[DISPC_OVL_BASE(i) + j]);
for (j = 0; j < 8; j++)
dispc_write_reg(
dispc, DISPC_FIR_COEF_HV2_OFFSET(i, j),
dispc->ctx[DISPC_OVL_BASE(i) + DISPC_FIR_COEF_HV2_OFFSET(i, j)]);
for (j = 0; j < 8; j++)
dispc_write_reg(
dispc, i + DISPC_FIR_COEF_V2_OFFSET(i, j),
dispc->ctx[DISPC_OVL_BASE(i) + DISPC_FIR_COEF_V2_OFFSET(i, j)]);
}
}
}
static int dispc_dump_regs(struct seq_file *s) {
struct dispc_device *dispc = s->private;
int i, j;
const char *mgr_names[] = {};
const char *ovl_names[] = {};
const char **p_names = mgr_names;
p_names = ovl_names;
for (i = j = 0;;)
seq_printf(s, p_names[i], dispc_read_reg(dispc, 0));
return 0;
}
int dispc_errata_i734_wa_init(struct dispc_device *);
struct soc_device_attribute dispc_soc_devices[] = {};
int dispc_bind(struct device dev) {
struct platform_device *pdev = 0;
struct soc_device_attribute *soc;
struct dss_device *dss;
struct dispc_device *dispc;
u32 rev;
int r;
struct device_node *np = dev.of_node;
dispc = 0;
soc = dispc_soc_devices;
if (soc)
;
r = dispc_errata_i734_wa_init(dispc);
if (of_property_read_bool(np, ""))
goto err_free;
goto err_runtime_get;
_dev_printk(rev);
dss_debugfs_create_file(dss, "", dispc_dump_regs, dispc);
err_runtime_get:
pm_runtime_disable(&pdev->dev);
err_free:
return r;
}
int dispc_runtime_suspend(struct device *dev) {
struct dispc_device *dispc = dev_get_drvdata(dev);
dispc_save_context(dispc);
return 0;
}
int dispc_runtime_resume(struct device *dev) {
struct dispc_device *dispc = dev_get_drvdata(dev);
dispc_restore_context(dispc);
return 0;
}
```
With this reproducer, the stack usage is much higher than compared to GCC (which appears to use no stack at all):
```
$ clang --target=x86_64-linux-gnu -O2 -Wall -Wframe-larger-than=64 -c -o /dev/null dispc.i
dispc.i:168:5: warning: stack frame size (2152) exceeds limit (64) in 'dispc_runtime_suspend' [-Wframe-larger-than]
168 | int dispc_runtime_suspend(struct device *dev) {
| ^
dispc.i:173:5: warning: stack frame size (2136) exceeds limit (64) in 'dispc_runtime_resume' [-Wframe-larger-than]
173 | int dispc_runtime_resume(struct device *dev) {
| ^
2 warnings generated.
$ x86_64-linux-gcc -O2 -Wall -Wframe-larger-than=1 -c -o /dev/null dispc.i
```
```
$ clang --target=aarch64-linux-gnu -O2 -Wall -Wframe-larger-than=64 -c -o /dev/null dispc.i
dispc.i:168:5: warning: stack frame size (2048) exceeds limit (64) in 'dispc_runtime_suspend' [-Wframe-larger-than]
168 | int dispc_runtime_suspend(struct device *dev) {
| ^
dispc.i:173:5: warning: stack frame size (1760) exceeds limit (64) in 'dispc_runtime_resume' [-Wframe-larger-than]
173 | int dispc_runtime_resume(struct device *dev) {
| ^
2 warnings generated.
$ aarch64-linux-gcc -O2 -Wall -Wframe-larger-than=1 -c -o /dev/null dispc.i
```
```
$ clang --target=loongarch64-linux-gnu -O2 -Wall -Wframe-larger-than=64 -c -o /dev/null dispc.i
dispc.i:168:5: warning: stack frame size (2144) exceeds limit (64) in 'dispc_runtime_suspend' [-Wframe-larger-than]
168 | int dispc_runtime_suspend(struct device *dev) {
| ^
dispc.i:173:5: warning: stack frame size (2112) exceeds limit (64) in 'dispc_runtime_resume' [-Wframe-larger-than]
173 | int dispc_runtime_resume(struct device *dev) {
| ^
2 warnings generated.
$ loongarch64-linux-gcc -O2 -Wall -Wframe-larger-than=1 -c -o /dev/null dispc.i
```
The Linux kernel uses `-Wframe-larger-than=2048`. This warning appears not to occur with `-Os`.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzkWt2T2jgS_2s0L11QtgwGHnjgY9hNVa5ma5NL7s0lZGFrYiSfJMPk_vorycbYYL6ySXbvNkUGY3W3-tdfaskmWvNEMDZFwzkaLp9IYVKppoKYlAhq_7OntYy_Tl8KBVQKw0UhCw1cGJYoYrgUIKThlMVg9hIE2wMX2lhGDXIDKPR6nzeKbFkvIyphqmclo9CDfcoErAuexVwksJHK0s5-X_yKgmUmpUiIoqklJJlJZZGkwA3Ekmk7IZA8Z0SBkbBm8N6SzxRNQeeM8g2nQDaGKVAsLqgVb1IGG54xiOVewJ6b1M5Gd1wzFHp95C2RN6v-hl75oeVv8zVnMduATqUyEEWFH6Jg3h7jwo0E-GzE0UMXj6OHJg8TxRbQaA5GFQzQaAkH2rWUWU22kzyGKGa7KFdcmC8Ij2lKFMKTmkQbVVADMdtxaiVVtwFaA5GQMQOEZ3LjLmt2NFq2Z0N4ZudLmIlitYuJIQiPTybBs6YGFlsUKbKPFCNxhvD4IIjEsdXVAVXMFEqUvGPLUkpxJMHcmqAJ2YnbK25YVpHvSFYwhBfQJbxLKqBgWXE15VdQNPt35KKkYbGD5FzxHTEtGzl654PN0RxHGXbSBfT7_aZdrCdBbqJcyZwp89WZJ3L-PbFo7R0rxTr41MQVdZ4Rs5FqG93wtv1qaZ9vI1UIw7csirkm64zdcuoBoqTVZBExRvF1YcppG2HjYlluSR7lGREsskasFXv5x-y3aPnhQ_TL6l8ILw7q1rc_vVs-v_gXR_BxpD0QdLF87gjqA0qtoyPS8te6SDY6oooRw5wjG0ZpkbfdsrA1AOGxNVetxCF2Wonhh7B89-G3RfTy6X00n314RnjcYS13UYVy7c89NzQFhMddo5Ro1jZtUJW0Q575eFzrcUpf2bxmAai5xje4cBfXKLzOFHQxBZ53kevzvIujSV-nM0SRXVgMF1EhFCM0raK76Yia-uiR2WLxTxx50ctq9eH544_xy2U7jwcNLDHbkCIzLbp7UDWs0AFw9e73aPHyvIp-xfeAXNiFC_gPQcttYsD4GuTviffTnw7YH-ABIDz_ych_FvDu9MQtzFcD_FsxH4oz1zm9sgaelvqGzEyKBKhULKLZl0g1V_lq0OyivGPM9hbUvKHh3PfwAA2XJ2MIzxKy3ZLIOCzD-QlNS_UNI6ZQTFsue325GyvpXSMUKZY0FqiWDfDM_a6dG7-5y7JtOvHlSW_lCBalvNJ_lrmrdga4mtX1MQ9q01Khiph203hbA22I4RQahtFkxyK7V2Fv5qY2LRVsG8-thq8NJ7mdCR5z1zq65SaYW6q5-7T4a-LXmtiJgteavCJtyIe2hFqG4wMULGDcKcIB6KHguYzAs56iTGZsOYdLp8-Zo5qzlv9qH10Wd2UlqWxnW6BJC2GnYa5ga2pzD8Rr1f6oVGmGC6CbdqmtwB-Q_gchfyvWO6A-iO8ueMdeq6sin6akYtq4-voNWfnzktL9O05ykpbnVbc2o3ds-R9041nHyUvvtcx9ZWZel-kbc57KfKTSwE0DdOdJdxwtzhPwLBnvLWstSN9eYlqgbhbFm4WgA-F3r2Tfpdzci_uRMvEdwd-L_ViLLhcjW0WqYlNscwtZd5_Z6NMe-EqhcqbWFtnp6dCFXoJKoU19arBNVCTIluny8NVJOzlGOWWRu-xRFoRnecnjqI-THhma48cZLlTb12bNPQZU-yzMAs9rTblz2uLKQuSdLTFn-_vao0dXMqWIIREfBYNoTyIu-JWl5d6DrKqJrIeumPqoyZqL-Oz0LGa77mA6O7LDszxmu6Nh2-Td5214piXt2Exc2ehcXXTbWxfVOCwsg1l1CGofVIq8bDPZrn96ogxwTJgWQkkbrWnT6I3JNzb4LNiu9lk1-Lvj4dBTnIm8dAwrchuSCGP3mbTWjEQaCUypaKNYE159_3CkmjDTGG4f1ysXGE3jXDx6tA5sKLM4L2ILOAN4psdhj9155ItwaKPPlrG4rdgR5-wkLdW1tDxMoQuds468KJ8mPFpnzx9AxGdm7Nr_dbj_ntpyAKGYLradJ-M_BMOlfvkhFPUjrOqn-_uZmxRMyjUolisZF5QpGz0mZaANoV-g0CRhwDVsC5pCypOUKTApEUDlNieKxWAk_LKw4Tjep5ym1WM4be8XmoGQlShigGSZ03fWVOJUMzwAmhGRQK9niHKxunwbh1E46GVcFG-9RBTQe8HQ-0yyDLoeJQbLcAA9Cj0JCK-cPVeiyLLSlH1eznT4Ecz8cIyC2RAFM9gTJbhI7GWptpMOmv_H-m2M_aHNf2BvlLFYQ8a33NiBcGBvcwEIjy6E_AjQcN6l7rDuVfxwDGi0gD-YOGUHtAA0fD6DOgruhhqED0I9JMY9SEfBBaSPZNcBqPs-gMUHZBoSJpgihsXtx7l4AO2IovRmRPm3A6ozx-4Jb0IUTf8a8e0Nxn-T-PZHoff_G98nIfUnB3j98sZfI8j9weBvEuTY9x9dr_6HgrwjrH5goH9MGby3s8AXpgTLbHujL73NFCxdKQ29Pny0DVaFpu6OhDS2Q5KUFqp--aj3oi3HUzwN4kkwIU9s6o-w74-xP8ZP6XRCyXodj7w1ZSM6wZPNehizYO0P_HDgk_XkiU-xhwfeyB952JsMcH8YB94oDomPR8QLRyEaeGxLeNbPst22L1XyxLUu2HQyweHwKSNrlmn34hfG7r0tO2h3GcPlk5pant66SDQaeBnXRh-lGG4yNv2VJ2m7cRQtiyE80hArvmNKI7xK8sL6QG0RXsktycsrt71Zle6gT4XKpqkxubZdI15ZLm7SYt2n0hJbBaqvXq7kK6MG4ZVT20opYe2m-L8BAAD__7tfT9s">