SelectionDAG Scheduler Caused Unnecessary Large Ppills For Bpf Programs
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The issue is reported by @dramforever:
https://github.com/llvm/llvm-project/issues/164792
The original code:
```
$ cat t.c
int meow[512 / sizeof(int)];
void cpy(char *dest)
{
__builtin_memcpy(dest, meow, 512);
}
```
With latest llvm22 or (llvm20, llvm21),
```
$ clang --target=bpf -O2 -c t.c -mcpu=v1 <=== success
$ clang --target=bpf -O2 -c t.c -mcpu=v3 <=== error
:3:6: error: Looks like the BPF stack limit is exceeded. Please move large on stack variables into BPF per-cpu array map. For non-kernel uses, the stack can be increased using -mllvm -bpf-stack-size.
...
```
So at cpu v1, the stack usage is 0, while at cpu v3, the stack usage is 968. The kernel bpf allows
maximum stack size of 512. So the stack usage 968 exceeds 512 and bpf back issues an error for it.
To simply the debugging, I changed the code as below
```
$ cat t.c
#define SIZE 40
int meow[SIZE / sizeof(int)];
void cpy(char *dest)
{
__builtin_memcpy(dest, (char *)meow, SIZE);
}
```
With below cpu v1 with max allowed stack size 8 bytes:
```
$ clang --target=bpf -O2 -c t.c -mcpu=v1 -mllvm -bpf-stack-size=8 -mllvm -debug-only=isel
...
===== Instruction selection ends:
Selected selection DAG: %bb.0 'cpy:entry'
SelectionDAG has 127 nodes:
t0: ch,glue = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %0
t88: i64 = LDIMM64 TargetGlobalAddress:i64 0
t81: i64,ch = LDW t88, TargetConstant:i64<0>, t0
t54: i64,ch = LDW t88, TargetConstant:i64<36>, t0
t60: i64,ch = LDW t88, TargetConstant:i64<28>, t0
t66: i64,ch = LDW t88, TargetConstant:i64<20>, t0
t72: i64,ch = LDW t88, TargetConstant:i64<12>, t0
t70: i64,ch = LDW t88, TargetConstant:i64<8>, t0
t64: i64,ch = LDW t88, TargetConstant:i64<16>, t0
t58: i64,ch = LDW t88, TargetConstant:i64<24>, t0
t52: i64,ch = LDW t88, TargetConstant:i64<32>, t0
t83: i64,ch = LDW t88, TargetConstant:i64<4>, t0
t254: ch = STB t81, t2, TargetConstant:i64<0>, t0
t253: i64 = SRL_ri t81, TargetConstant:i64<8>
t229: ch = STB t253, t2, TargetConstant:i64<1>, t0
t95: i64 = SRL_ri t81, TargetConstant:i64<16>
t222: ch = STB t95, t2, TargetConstant:i64<2>, t0
t258: i64 = SRL_ri t81, TargetConstant:i64<24>
t224: ch = STB t258, t2, TargetConstant:i64<3>, t0
t237: ch = STB t83, t2, TargetConstant:i64<4>, t0
t236: i64 = SRL_ri t83, TargetConstant:i64<8>
t239: ch = STB t236, t2, TargetConstant:i64<5>, t0
t89: i64 = SRL_ri t83, TargetConstant:i64<16>
t232: ch = STB t89, t2, TargetConstant:i64<6>, t0
t252: i64 = SRL_ri t83, TargetConstant:i64<24>
t234: ch = STB t252, t2, TargetConstant:i64<7>, t0
t275: ch = STB t70, t2, TargetConstant:i64<8>, t0
t272: i64 = SRL_ri t70, TargetConstant:i64<8>
t209: ch = STB t272, t2, TargetConstant:i64<9>, t0
t105: i64 = SRL_ri t70, TargetConstant:i64<16>
t202: ch = STB t105, t2, TargetConstant:i64<10>, t0
t280: i64 = SRL_ri t70, TargetConstant:i64<24>
t204: ch = STB t280, t2, TargetConstant:i64<11>, t0
t217: ch = STB t72, t2, TargetConstant:i64<12>, t0
t216: i64 = SRL_ri t72, TargetConstant:i64<8>
t219: ch = STB t216, t2, TargetConstant:i64<13>, t0
t100: i64 = SRL_ri t72, TargetConstant:i64<16>
t212: ch = STB t100, t2, TargetConstant:i64<14>, t0
t271: i64 = SRL_ri t72, TargetConstant:i64<24>
t214: ch = STB t271, t2, TargetConstant:i64<15>, t0
t297: ch = STB t64, t2, TargetConstant:i64<16>, t0
t294: i64 = SRL_ri t64, TargetConstant:i64<8>
t189: ch = STB t294, t2, TargetConstant:i64<17>, t0
t115: i64 = SRL_ri t64, TargetConstant:i64<16>
t182: ch = STB t115, t2, TargetConstant:i64<18>, t0
t302: i64 = SRL_ri t64, TargetConstant:i64<24>
t184: ch = STB t302, t2, TargetConstant:i64<19>, t0
t197: ch = STB t66, t2, TargetConstant:i64<20>, t0
t196: i64 = SRL_ri t66, TargetConstant:i64<8>
t199: ch = STB t196, t2, TargetConstant:i64<21>, t0
t110: i64 = SRL_ri t66, TargetConstant:i64<16>
t192: ch = STB t110, t2, TargetConstant:i64<22>, t0
t293: i64 = SRL_ri t66, TargetConstant:i64<24>
t194: ch = STB t293, t2, TargetConstant:i64<23>, t0
t319: ch = STB t58, t2, TargetConstant:i64<24>, t0
t316: i64 = SRL_ri t58, TargetConstant:i64<8>
t169: ch = STB t316, t2, TargetConstant:i64<25>, t0
t125: i64 = SRL_ri t58, TargetConstant:i64<16>
t162: ch = STB t125, t2, TargetConstant:i64<26>, t0
t324: i64 = SRL_ri t58, TargetConstant:i64<24>
t164: ch = STB t324, t2, TargetConstant:i64<27>, t0
t177: ch = STB t60, t2, TargetConstant:i64<28>, t0
t176: i64 = SRL_ri t60, TargetConstant:i64<8>
t179: ch = STB t176, t2, TargetConstant:i64<29>, t0
t120: i64 = SRL_ri t60, TargetConstant:i64<16>
t172: ch = STB t120, t2, TargetConstant:i64<30>, t0
t315: i64 = SRL_ri t60, TargetConstant:i64<24>
t174: ch = STB t315, t2, TargetConstant:i64<31>, t0
t341: ch = STB t52, t2, TargetConstant:i64<32>, t0
t338: i64 = SRL_ri t52, TargetConstant:i64<8>
t149: ch = STB t338, t2, TargetConstant:i64<33>, t0
t135: i64 = SRL_ri t52, TargetConstant:i64<16>
t141: ch = STB t135, t2, TargetConstant:i64<34>, t0
t346: i64 = SRL_ri t52, TargetConstant:i64<24>
t144: ch = STB t346, t2, TargetConstant:i64<35>, t0
t157: ch = STB t54, t2, TargetConstant:i64<36>, t0
t156: i64 = SRL_ri t54, TargetConstant:i64<8>
t159: ch = STB t156, t2, TargetConstant:i64<37>, t0
t130: i64 = SRL_ri t54, TargetConstant:i64<16>
t152: ch = STB t130, t2, TargetConstant:i64<38>, t0
t337: i64 = SRL_ri t54, TargetConstant:i64<24>
t154: ch = STB t337, t2, TargetConstant:i64<39>, t0
t405: ch = TokenFactor t81:1, t83:1, t254, t229, t222, t224, t237, t239, t232, t234, t70:1, t72:1, t275, t209, t202, t204, t217, t219, t212, t214, t64:1, t66:1, t297, t189, t182, t184, t197, t199, t192, t194, t58:1, t60:1, t319, t169, t162, t164, t177, t179, t172, t174, t52:1, t54:1, t341, t149, t141, t144, t157, t159, t152, t154
t30: ch = RET t405
Total amount of phi nodes to update: 0
*** MachineFunction at end of ISel ***
# Machine code for function cpy: IsSSA, TracksLiveness
Function Live Ins: $r1 in %0
bb.0.entry:
liveins: $r1
%0:gpr = COPY $r1
%1:gpr = LDIMM64 @meow
%2:gpr = LDW %1:gpr, 36 :: (dereferenceable load (s32) from @meow + 36)
%3:gpr = SRL_ri %2:gpr(tied-def 0), 24
STB killed %3:gpr, %0:gpr, 39 :: (store (s8) into %ir.dest + 39)
%4:gpr = SRL_ri %2:gpr(tied-def 0), 16
STB killed %4:gpr, %0:gpr, 38 :: (store (s8) into %ir.dest + 38)
STB %2:gpr, %0:gpr, 36 :: (store (s8) into %ir.dest + 36)
%5:gpr = SRL_ri %2:gpr(tied-def 0), 8
STB killed %5:gpr, %0:gpr, 37 :: (store (s8) into %ir.dest + 37)
%6:gpr = LDW %1:gpr, 32 :: (dereferenceable load (s32) from @meow + 32)
%7:gpr = SRL_ri %6:gpr(tied-def 0), 24
STB killed %7:gpr, %0:gpr, 35 :: (store (s8) into %ir.dest + 35)
%8:gpr = SRL_ri %6:gpr(tied-def 0), 16
STB killed %8:gpr, %0:gpr, 34 :: (store (s8) into %ir.dest + 34)
STB %6:gpr, %0:gpr, 32 :: (store (s8) into %ir.dest + 32)
%9:gpr = SRL_ri %6:gpr(tied-def 0), 8
STB killed %9:gpr, %0:gpr, 33 :: (store (s8) into %ir.dest + 33)
%10:gpr = LDW %1:gpr, 28 :: (dereferenceable load (s32) from @meow + 28)
%11:gpr = SRL_ri %10:gpr(tied-def 0), 24
STB killed %11:gpr, %0:gpr, 31 :: (store (s8) into %ir.dest + 31)
%12:gpr = SRL_ri %10:gpr(tied-def 0), 16
STB killed %12:gpr, %0:gpr, 30 :: (store (s8) into %ir.dest + 30)
STB %10:gpr, %0:gpr, 28 :: (store (s8) into %ir.dest + 28)
%13:gpr = SRL_ri %10:gpr(tied-def 0), 8
STB killed %13:gpr, %0:gpr, 29 :: (store (s8) into %ir.dest + 29)
%14:gpr = LDW %1:gpr, 24 :: (dereferenceable load (s32) from @meow + 24)
%15:gpr = SRL_ri %14:gpr(tied-def 0), 24
STB killed %15:gpr, %0:gpr, 27 :: (store (s8) into %ir.dest + 27)
%16:gpr = SRL_ri %14:gpr(tied-def 0), 16
STB killed %16:gpr, %0:gpr, 26 :: (store (s8) into %ir.dest + 26)
STB %14:gpr, %0:gpr, 24 :: (store (s8) into %ir.dest + 24)
%17:gpr = SRL_ri %14:gpr(tied-def 0), 8
STB killed %17:gpr, %0:gpr, 25 :: (store (s8) into %ir.dest + 25)
%18:gpr = LDW %1:gpr, 20 :: (dereferenceable load (s32) from @meow + 20)
%19:gpr = SRL_ri %18:gpr(tied-def 0), 24
STB killed %19:gpr, %0:gpr, 23 :: (store (s8) into %ir.dest + 23)
%20:gpr = SRL_ri %18:gpr(tied-def 0), 16
STB killed %20:gpr, %0:gpr, 22 :: (store (s8) into %ir.dest + 22)
STB %18:gpr, %0:gpr, 20 :: (store (s8) into %ir.dest + 20)
%21:gpr = SRL_ri %18:gpr(tied-def 0), 8
STB killed %21:gpr, %0:gpr, 21 :: (store (s8) into %ir.dest + 21)
%22:gpr = LDW %1:gpr, 16 :: (dereferenceable load (s32) from @meow + 16)
%23:gpr = SRL_ri %22:gpr(tied-def 0), 24
STB killed %23:gpr, %0:gpr, 19 :: (store (s8) into %ir.dest + 19)
%24:gpr = SRL_ri %22:gpr(tied-def 0), 16
STB killed %24:gpr, %0:gpr, 18 :: (store (s8) into %ir.dest + 18)
STB %22:gpr, %0:gpr, 16 :: (store (s8) into %ir.dest + 16)
%25:gpr = SRL_ri %22:gpr(tied-def 0), 8
STB killed %25:gpr, %0:gpr, 17 :: (store (s8) into %ir.dest + 17)
%26:gpr = LDW %1:gpr, 12 :: (dereferenceable load (s32) from @meow + 12)
%27:gpr = SRL_ri %26:gpr(tied-def 0), 24
STB killed %27:gpr, %0:gpr, 15 :: (store (s8) into %ir.dest + 15)
%28:gpr = SRL_ri %26:gpr(tied-def 0), 16
STB killed %28:gpr, %0:gpr, 14 :: (store (s8) into %ir.dest + 14)
STB %26:gpr, %0:gpr, 12 :: (store (s8) into %ir.dest + 12)
%29:gpr = SRL_ri %26:gpr(tied-def 0), 8
STB killed %29:gpr, %0:gpr, 13 :: (store (s8) into %ir.dest + 13)
%30:gpr = LDW %1:gpr, 8 :: (dereferenceable load (s32) from @meow + 8)
%31:gpr = SRL_ri %30:gpr(tied-def 0), 24
STB killed %31:gpr, %0:gpr, 11 :: (store (s8) into %ir.dest + 11)
%32:gpr = SRL_ri %30:gpr(tied-def 0), 16
STB killed %32:gpr, %0:gpr, 10 :: (store (s8) into %ir.dest + 10)
STB %30:gpr, %0:gpr, 8 :: (store (s8) into %ir.dest + 8)
%33:gpr = SRL_ri %30:gpr(tied-def 0), 8
STB killed %33:gpr, %0:gpr, 9 :: (store (s8) into %ir.dest + 9)
%34:gpr = LDW %1:gpr, 4 :: (dereferenceable load (s32) from @meow + 4)
%35:gpr = SRL_ri %34:gpr(tied-def 0), 24
STB killed %35:gpr, %0:gpr, 7 :: (store (s8) into %ir.dest + 7)
%36:gpr = SRL_ri %34:gpr(tied-def 0), 16
STB killed %36:gpr, %0:gpr, 6 :: (store (s8) into %ir.dest + 6)
STB %34:gpr, %0:gpr, 4 :: (store (s8) into %ir.dest + 4)
%37:gpr = SRL_ri %34:gpr(tied-def 0), 8
STB killed %37:gpr, %0:gpr, 5 :: (store (s8) into %ir.dest + 5)
%38:gpr = LDW %1:gpr, 0 :: (dereferenceable load (s32) from @meow)
%39:gpr = SRL_ri %38:gpr(tied-def 0), 24
STB killed %39:gpr, %0:gpr, 3 :: (store (s8) into %ir.dest + 3)
%40:gpr = SRL_ri %38:gpr(tied-def 0), 16
STB killed %40:gpr, %0:gpr, 2 :: (store (s8) into %ir.dest + 2)
STB %38:gpr, %0:gpr, 0 :: (store (s8) into %ir.dest)
%41:gpr = SRL_ri %38:gpr(tied-def 0), 8
STB killed %41:gpr, %0:gpr, 1 :: (store (s8) into %ir.dest + 1)
RET
# End machine code for function cpy.
```
The below cpu v3 with max allowed stack size 8 bytes:
```
$ clang --target=bpf -O2 -c t.c -mcpu=v3 -mllvm -bpf-stack-size=8 -mllvm -debug-only=isel
...
===== Instruction selection ends:
Selected selection DAG: %bb.0 'cpy:entry'
SelectionDAG has 178 nodes:
t0: ch,glue = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %0
t88: i64 = LDIMM64 TargetGlobalAddress:i64 0
t81: i64,ch = SUBREG_TO_REG TargetConstant:i64<0>, t496, TargetConstant:i32<1>, t496:1
t54: i64,ch = SUBREG_TO_REG TargetConstant:i64<0>, t495, TargetConstant:i32<1>, t495:1
t60: i64,ch = SUBREG_TO_REG TargetConstant:i64<0>, t494, TargetConstant:i32<1>, t494:1
t66: i64,ch = SUBREG_TO_REG TargetConstant:i64<0>, t493, TargetConstant:i32<1>, t493:1
t72: i64,ch = SUBREG_TO_REG TargetConstant:i64<0>, t492, TargetConstant:i32<1>, t492:1
t70: i64,ch = SUBREG_TO_REG TargetConstant:i64<0>, t491, TargetConstant:i32<1>, t491:1
t64: i64,ch = SUBREG_TO_REG TargetConstant:i64<0>, t490, TargetConstant:i32<1>, t490:1
t58: i64,ch = SUBREG_TO_REG TargetConstant:i64<0>, t489, TargetConstant:i32<1>, t489:1
t52: i64,ch = SUBREG_TO_REG TargetConstant:i64<0>, t488, TargetConstant:i32<1>, t488:1
t83: i64,ch = SUBREG_TO_REG TargetConstant:i64<0>, t486, TargetConstant:i32<1>, t486:1
t486: i32,ch = LDW32 t88, TargetConstant:i64<4>, t0
t488: i32,ch = LDW32 t88, TargetConstant:i64<32>, t0
t489: i32,ch = LDW32 t88, TargetConstant:i64<24>, t0
t490: i32,ch = LDW32 t88, TargetConstant:i64<16>, t0
t491: i32,ch = LDW32 t88, TargetConstant:i64<8>, t0
t492: i32,ch = LDW32 t88, TargetConstant:i64<12>, t0
t493: i32,ch = LDW32 t88, TargetConstant:i64<20>, t0
t494: i32,ch = LDW32 t88, TargetConstant:i64<28>, t0
t495: i32,ch = LDW32 t88, TargetConstant:i64<36>, t0
t496: i32,ch = LDW32 t88, TargetConstant:i64<0>, t0
t487: i32 = EXTRACT_SUBREG t81, TargetConstant:i32<1>
t254: ch = STB32 t487, t2, TargetConstant:i64<0>, t0
t253: i64 = SRL_ri t81, TargetConstant:i64<8>
t467: i32 = EXTRACT_SUBREG t253, TargetConstant:i32<1>
t229: ch = STB32 t467, t2, TargetConstant:i64<1>, t0
t95: i64 = SRL_ri t81, TargetConstant:i64<16>
t471: i32 = EXTRACT_SUBREG t95, TargetConstant:i32<1>
t222: ch = STB32 t471, t2, TargetConstant:i64<2>, t0
t258: i64 = SRL_ri t81, TargetConstant:i64<24>
t469: i32 = EXTRACT_SUBREG t258, TargetConstant:i32<1>
t224: ch = STB32 t469, t2, TargetConstant:i64<3>, t0
t462: i32 = EXTRACT_SUBREG t83, TargetConstant:i32<1>
t237: ch = STB32 t462, t2, TargetConstant:i64<4>, t0
t236: i64 = SRL_ri t83, TargetConstant:i64<8>
t408: i32 = EXTRACT_SUBREG t236, TargetConstant:i32<1>
t239: ch = STB32 t408, t2, TargetConstant:i64<5>, t0
t89: i64 = SRL_ri t83, TargetConstant:i64<16>
t410: i32 = EXTRACT_SUBREG t89, TargetConstant:i32<1>
t232: ch = STB32 t410, t2, TargetConstant:i64<6>, t0
t252: i64 = SRL_ri t83, TargetConstant:i64<24>
t412: i32 = EXTRACT_SUBREG t252, TargetConstant:i32<1>
t234: ch = STB32 t412, t2, TargetConstant:i64<7>, t0
t476: i32 = EXTRACT_SUBREG t70, TargetConstant:i32<1>
t275: ch = STB32 t476, t2, TargetConstant:i64<8>, t0
t272: i64 = SRL_ri t70, TargetConstant:i64<8>
t432: i32 = EXTRACT_SUBREG t272, TargetConstant:i32<1>
t209: ch = STB32 t432, t2, TargetConstant:i64<9>, t0
t105: i64 = SRL_ri t70, TargetConstant:i64<16>
t436: i32 = EXTRACT_SUBREG t105, TargetConstant:i32<1>
t202: ch = STB32 t436, t2, TargetConstant:i64<10>, t0
t280: i64 = SRL_ri t70, TargetConstant:i64<24>
t434: i32 = EXTRACT_SUBREG t280, TargetConstant:i32<1>
t204: ch = STB32 t434, t2, TargetConstant:i64<11>, t0
t478: i32 = EXTRACT_SUBREG t72, TargetConstant:i32<1>
t217: ch = STB32 t478, t2, TargetConstant:i64<12>, t0
t216: i64 = SRL_ri t72, TargetConstant:i64<8>
t438: i32 = EXTRACT_SUBREG t216, TargetConstant:i32<1>
t219: ch = STB32 t438, t2, TargetConstant:i64<13>, t0
t100: i64 = SRL_ri t72, TargetConstant:i64<16>
t440: i32 = EXTRACT_SUBREG t100, TargetConstant:i32<1>
t212: ch = STB32 t440, t2, TargetConstant:i64<14>, t0
t271: i64 = SRL_ri t72, TargetConstant:i64<24>
t442: i32 = EXTRACT_SUBREG t271, TargetConstant:i32<1>
t214: ch = STB32 t442, t2, TargetConstant:i64<15>, t0
t475: i32 = EXTRACT_SUBREG t64, TargetConstant:i32<1>
t297: ch = STB32 t475, t2, TargetConstant:i64<16>, t0
t294: i64 = SRL_ri t64, TargetConstant:i64<8>
t426: i32 = EXTRACT_SUBREG t294, TargetConstant:i32<1>
t189: ch = STB32 t426, t2, TargetConstant:i64<17>, t0
t115: i64 = SRL_ri t64, TargetConstant:i64<16>
t430: i32 = EXTRACT_SUBREG t115, TargetConstant:i32<1>
t182: ch = STB32 t430, t2, TargetConstant:i64<18>, t0
t302: i64 = SRL_ri t64, TargetConstant:i64<24>
t428: i32 = EXTRACT_SUBREG t302, TargetConstant:i32<1>
t184: ch = STB32 t428, t2, TargetConstant:i64<19>, t0
t480: i32 = EXTRACT_SUBREG t66, TargetConstant:i32<1>
t197: ch = STB32 t480, t2, TargetConstant:i64<20>, t0
t196: i64 = SRL_ri t66, TargetConstant:i64<8>
t444: i32 = EXTRACT_SUBREG t196, TargetConstant:i32<1>
t199: ch = STB32 t444, t2, TargetConstant:i64<21>, t0
t110: i64 = SRL_ri t66, TargetConstant:i64<16>
t446: i32 = EXTRACT_SUBREG t110, TargetConstant:i32<1>
t192: ch = STB32 t446, t2, TargetConstant:i64<22>, t0
t293: i64 = SRL_ri t66, TargetConstant:i64<24>
t448: i32 = EXTRACT_SUBREG t293, TargetConstant:i32<1>
t194: ch = STB32 t448, t2, TargetConstant:i64<23>, t0
t474: i32 = EXTRACT_SUBREG t58, TargetConstant:i32<1>
t319: ch = STB32 t474, t2, TargetConstant:i64<24>, t0
t316: i64 = SRL_ri t58, TargetConstant:i64<8>
t420: i32 = EXTRACT_SUBREG t316, TargetConstant:i32<1>
t169: ch = STB32 t420, t2, TargetConstant:i64<25>, t0
t125: i64 = SRL_ri t58, TargetConstant:i64<16>
t424: i32 = EXTRACT_SUBREG t125, TargetConstant:i32<1>
t162: ch = STB32 t424, t2, TargetConstant:i64<26>, t0
t324: i64 = SRL_ri t58, TargetConstant:i64<24>
t422: i32 = EXTRACT_SUBREG t324, TargetConstant:i32<1>
t164: ch = STB32 t422, t2, TargetConstant:i64<27>, t0
t482: i32 = EXTRACT_SUBREG t60, TargetConstant:i32<1>
t177: ch = STB32 t482, t2, TargetConstant:i64<28>, t0
t176: i64 = SRL_ri t60, TargetConstant:i64<8>
t450: i32 = EXTRACT_SUBREG t176, TargetConstant:i32<1>
t179: ch = STB32 t450, t2, TargetConstant:i64<29>, t0
t120: i64 = SRL_ri t60, TargetConstant:i64<16>
t452: i32 = EXTRACT_SUBREG t120, TargetConstant:i32<1>
t172: ch = STB32 t452, t2, TargetConstant:i64<30>, t0
t315: i64 = SRL_ri t60, TargetConstant:i64<24>
t454: i32 = EXTRACT_SUBREG t315, TargetConstant:i32<1>
t174: ch = STB32 t454, t2, TargetConstant:i64<31>, t0
t473: i32 = EXTRACT_SUBREG t52, TargetConstant:i32<1>
t341: ch = STB32 t473, t2, TargetConstant:i64<32>, t0
t338: i64 = SRL_ri t52, TargetConstant:i64<8>
t414: i32 = EXTRACT_SUBREG t338, TargetConstant:i32<1>
t149: ch = STB32 t414, t2, TargetConstant:i64<33>, t0
t135: i64 = SRL_ri t52, TargetConstant:i64<16>
t418: i32 = EXTRACT_SUBREG t135, TargetConstant:i32<1>
t141: ch = STB32 t418, t2, TargetConstant:i64<34>, t0
t346: i64 = SRL_ri t52, TargetConstant:i64<24>
t416: i32 = EXTRACT_SUBREG t346, TargetConstant:i32<1>
t144: ch = STB32 t416, t2, TargetConstant:i64<35>, t0
t484: i32 = EXTRACT_SUBREG t54, TargetConstant:i32<1>
t157: ch = STB32 t484, t2, TargetConstant:i64<36>, t0
t156: i64 = SRL_ri t54, TargetConstant:i64<8>
t456: i32 = EXTRACT_SUBREG t156, TargetConstant:i32<1>
t159: ch = STB32 t456, t2, TargetConstant:i64<37>, t0
t130: i64 = SRL_ri t54, TargetConstant:i64<16>
t458: i32 = EXTRACT_SUBREG t130, TargetConstant:i32<1>
t152: ch = STB32 t458, t2, TargetConstant:i64<38>, t0
t337: i64 = SRL_ri t54, TargetConstant:i64<24>
t460: i32 = EXTRACT_SUBREG t337, TargetConstant:i32<1>
t154: ch = STB32 t460, t2, TargetConstant:i64<39>, t0
t405: ch = TokenFactor t81:1, t83:1, t254, t229, t222, t224, t237, t239, t232, t234, t70:1, t72:1, t275, t209, t202, t204, t217, t219, t212, t214, t64:1, t66:1, t297, t189, t182, t184, t197, t199, t192, t194, t58:1, t60:1, t319, t169, t162, t164, t177, t179, t172, t174, t52:1, t54:1, t341, t149, t141, t144, t157, t159, t152, t154
t30: ch = RET t405
Total amount of phi nodes to update: 0
*** MachineFunction at end of ISel ***
# Machine code for function cpy: IsSSA, TracksLiveness
Function Live Ins: $r1 in %0
bb.0.entry:
liveins: $r1
%0:gpr = COPY $r1
%1:gpr = LDIMM64 @meow
%2:gpr32 = LDW32 %1:gpr, 36 :: (dereferenceable load (s32) from @meow + 36)
%3:gpr = SUBREG_TO_REG 0, killed %2:gpr32, %subreg.sub_32
%4:gpr32 = COPY %3.sub_32:gpr
STB32 killed %4:gpr32, %0:gpr, 36 :: (store (s8) into %ir.dest + 36)
%5:gpr32 = LDW32 %1:gpr, 32 :: (dereferenceable load (s32) from @meow + 32)
%6:gpr = SUBREG_TO_REG 0, killed %5:gpr32, %subreg.sub_32
%7:gpr32 = COPY %6.sub_32:gpr
STB32 killed %7:gpr32, %0:gpr, 32 :: (store (s8) into %ir.dest + 32)
%8:gpr32 = LDW32 %1:gpr, 28 :: (dereferenceable load (s32) from @meow + 28)
%9:gpr = SUBREG_TO_REG 0, killed %8:gpr32, %subreg.sub_32
%10:gpr32 = COPY %9.sub_32:gpr
STB32 killed %10:gpr32, %0:gpr, 28 :: (store (s8) into %ir.dest + 28)
%11:gpr32 = LDW32 %1:gpr, 24 :: (dereferenceable load (s32) from @meow + 24)
%12:gpr = SUBREG_TO_REG 0, killed %11:gpr32, %subreg.sub_32
%13:gpr32 = COPY %12.sub_32:gpr
STB32 killed %13:gpr32, %0:gpr, 24 :: (store (s8) into %ir.dest + 24)
%14:gpr32 = LDW32 %1:gpr, 20 :: (dereferenceable load (s32) from @meow + 20)
%15:gpr = SUBREG_TO_REG 0, killed %14:gpr32, %subreg.sub_32
%16:gpr32 = COPY %15.sub_32:gpr
STB32 killed %16:gpr32, %0:gpr, 20 :: (store (s8) into %ir.dest + 20)
%17:gpr32 = LDW32 %1:gpr, 16 :: (dereferenceable load (s32) from @meow + 16)
%18:gpr = SUBREG_TO_REG 0, killed %17:gpr32, %subreg.sub_32
%19:gpr32 = COPY %18.sub_32:gpr
STB32 killed %19:gpr32, %0:gpr, 16 :: (store (s8) into %ir.dest + 16)
%20:gpr32 = LDW32 %1:gpr, 12 :: (dereferenceable load (s32) from @meow + 12)
%21:gpr = SUBREG_TO_REG 0, killed %20:gpr32, %subreg.sub_32
%22:gpr32 = COPY %21.sub_32:gpr
STB32 killed %22:gpr32, %0:gpr, 12 :: (store (s8) into %ir.dest + 12)
%23:gpr32 = LDW32 %1:gpr, 8 :: (dereferenceable load (s32) from @meow + 8)
%24:gpr = SUBREG_TO_REG 0, killed %23:gpr32, %subreg.sub_32
%25:gpr32 = COPY %24.sub_32:gpr
STB32 killed %25:gpr32, %0:gpr, 8 :: (store (s8) into %ir.dest + 8)
%26:gpr32 = LDW32 %1:gpr, 4 :: (dereferenceable load (s32) from @meow + 4)
%27:gpr = SUBREG_TO_REG 0, killed %26:gpr32, %subreg.sub_32
%28:gpr32 = COPY %27.sub_32:gpr
STB32 killed %28:gpr32, %0:gpr, 4 :: (store (s8) into %ir.dest + 4)
%29:gpr32 = LDW32 %1:gpr, 0 :: (dereferenceable load (s32) from @meow)
%30:gpr = SUBREG_TO_REG 0, killed %29:gpr32, %subreg.sub_32
%31:gpr32 = COPY %30.sub_32:gpr
STB32 killed %31:gpr32, %0:gpr, 0 :: (store (s8) into %ir.dest)
%32:gpr = SRL_ri %3:gpr(tied-def 0), 24
%33:gpr32 = COPY %32.sub_32:gpr
STB32 killed %33:gpr32, %0:gpr, 39 :: (store (s8) into %ir.dest + 39)
%34:gpr = SRL_ri %3:gpr(tied-def 0), 16
%35:gpr32 = COPY %34.sub_32:gpr
STB32 killed %35:gpr32, %0:gpr, 38 :: (store (s8) into %ir.dest + 38)
%36:gpr = SRL_ri %3:gpr(tied-def 0), 8
%37:gpr32 = COPY %36.sub_32:gpr
STB32 killed %37:gpr32, %0:gpr, 37 :: (store (s8) into %ir.dest + 37)
%38:gpr = SRL_ri %6:gpr(tied-def 0), 24
%39:gpr32 = COPY %38.sub_32:gpr
STB32 killed %39:gpr32, %0:gpr, 35 :: (store (s8) into %ir.dest + 35)
%40:gpr = SRL_ri %6:gpr(tied-def 0), 16
%41:gpr32 = COPY %40.sub_32:gpr
STB32 killed %41:gpr32, %0:gpr, 34 :: (store (s8) into %ir.dest + 34)
%42:gpr = SRL_ri %6:gpr(tied-def 0), 8
%43:gpr32 = COPY %42.sub_32:gpr
STB32 killed %43:gpr32, %0:gpr, 33 :: (store (s8) into %ir.dest + 33)
%44:gpr = SRL_ri %9:gpr(tied-def 0), 24
%45:gpr32 = COPY %44.sub_32:gpr
STB32 killed %45:gpr32, %0:gpr, 31 :: (store (s8) into %ir.dest + 31)
%46:gpr = SRL_ri %9:gpr(tied-def 0), 16
%47:gpr32 = COPY %46.sub_32:gpr
STB32 killed %47:gpr32, %0:gpr, 30 :: (store (s8) into %ir.dest + 30)
%48:gpr = SRL_ri %9:gpr(tied-def 0), 8
%49:gpr32 = COPY %48.sub_32:gpr
STB32 killed %49:gpr32, %0:gpr, 29 :: (store (s8) into %ir.dest + 29)
%50:gpr = SRL_ri %12:gpr(tied-def 0), 24
%51:gpr32 = COPY %50.sub_32:gpr
STB32 killed %51:gpr32, %0:gpr, 27 :: (store (s8) into %ir.dest + 27)
%52:gpr = SRL_ri %12:gpr(tied-def 0), 16
%53:gpr32 = COPY %52.sub_32:gpr
STB32 killed %53:gpr32, %0:gpr, 26 :: (store (s8) into %ir.dest + 26)
%54:gpr = SRL_ri %12:gpr(tied-def 0), 8
%55:gpr32 = COPY %54.sub_32:gpr
STB32 killed %55:gpr32, %0:gpr, 25 :: (store (s8) into %ir.dest + 25)
%56:gpr = SRL_ri %15:gpr(tied-def 0), 24
%57:gpr32 = COPY %56.sub_32:gpr
STB32 killed %57:gpr32, %0:gpr, 23 :: (store (s8) into %ir.dest + 23)
%58:gpr = SRL_ri %15:gpr(tied-def 0), 16
%59:gpr32 = COPY %58.sub_32:gpr
STB32 killed %59:gpr32, %0:gpr, 22 :: (store (s8) into %ir.dest + 22)
%60:gpr = SRL_ri %15:gpr(tied-def 0), 8
%61:gpr32 = COPY %60.sub_32:gpr
STB32 killed %61:gpr32, %0:gpr, 21 :: (store (s8) into %ir.dest + 21)
%62:gpr = SRL_ri %18:gpr(tied-def 0), 24
%63:gpr32 = COPY %62.sub_32:gpr
STB32 killed %63:gpr32, %0:gpr, 19 :: (store (s8) into %ir.dest + 19)
%64:gpr = SRL_ri %18:gpr(tied-def 0), 16
%65:gpr32 = COPY %64.sub_32:gpr
STB32 killed %65:gpr32, %0:gpr, 18 :: (store (s8) into %ir.dest + 18)
%66:gpr = SRL_ri %18:gpr(tied-def 0), 8
%67:gpr32 = COPY %66.sub_32:gpr
STB32 killed %67:gpr32, %0:gpr, 17 :: (store (s8) into %ir.dest + 17)
%68:gpr = SRL_ri %21:gpr(tied-def 0), 24
%69:gpr32 = COPY %68.sub_32:gpr
STB32 killed %69:gpr32, %0:gpr, 15 :: (store (s8) into %ir.dest + 15)
%70:gpr = SRL_ri %21:gpr(tied-def 0), 16
%71:gpr32 = COPY %70.sub_32:gpr
STB32 killed %71:gpr32, %0:gpr, 14 :: (store (s8) into %ir.dest + 14)
%72:gpr = SRL_ri %21:gpr(tied-def 0), 8
%73:gpr32 = COPY %72.sub_32:gpr
STB32 killed %73:gpr32, %0:gpr, 13 :: (store (s8) into %ir.dest + 13)
%74:gpr = SRL_ri %24:gpr(tied-def 0), 24
%75:gpr32 = COPY %74.sub_32:gpr
STB32 killed %75:gpr32, %0:gpr, 11 :: (store (s8) into %ir.dest + 11)
%76:gpr = SRL_ri %24:gpr(tied-def 0), 16
%77:gpr32 = COPY %76.sub_32:gpr
STB32 killed %77:gpr32, %0:gpr, 10 :: (store (s8) into %ir.dest + 10)
%78:gpr = SRL_ri %24:gpr(tied-def 0), 8
%79:gpr32 = COPY %78.sub_32:gpr
STB32 killed %79:gpr32, %0:gpr, 9 :: (store (s8) into %ir.dest + 9)
%80:gpr = SRL_ri %27:gpr(tied-def 0), 24
%81:gpr32 = COPY %80.sub_32:gpr
STB32 killed %81:gpr32, %0:gpr, 7 :: (store (s8) into %ir.dest + 7)
%82:gpr = SRL_ri %27:gpr(tied-def 0), 16
%83:gpr32 = COPY %82.sub_32:gpr
STB32 killed %83:gpr32, %0:gpr, 6 :: (store (s8) into %ir.dest + 6)
%84:gpr = SRL_ri %27:gpr(tied-def 0), 8
%85:gpr32 = COPY %84.sub_32:gpr
STB32 killed %85:gpr32, %0:gpr, 5 :: (store (s8) into %ir.dest + 5)
%86:gpr = SRL_ri %30:gpr(tied-def 0), 24
%87:gpr32 = COPY %86.sub_32:gpr
STB32 killed %87:gpr32, %0:gpr, 3 :: (store (s8) into %ir.dest + 3)
%88:gpr = SRL_ri %30:gpr(tied-def 0), 16
%89:gpr32 = COPY %88.sub_32:gpr
STB32 killed %89:gpr32, %0:gpr, 2 :: (store (s8) into %ir.dest + 2)
%90:gpr = SRL_ri %30:gpr(tied-def 0), 8
%91:gpr32 = COPY %90.sub_32:gpr
STB32 killed %91:gpr32, %0:gpr, 1 :: (store (s8) into %ir.dest + 1)
RET
# End machine code for function cpy.
t.c:3:6: error: Looks like the BPF stack limit is exceeded. Please move large on stack variables into BPF per-cpu array map. For non-kernel uses, the stack can be increased using -mllvm -bpf-stack-size.
3 | void cpy(char *dest)
| ^
...
6 errors generated.
```
In the above, for cpu v1, the byte copy almost contiguous so there is no register pressure
and hence eventual stack usage is 0.
For cpu v3, the byte copy between 4 * (0->9) and other not multiple 4 byte copy are
not closely adjacent to each other. Later on, this will cause register spills in register
allocation stage.
So my question is, can we do some optimization in SelectionDAG esp. in scheduler stage
to schedule sequence of codes for cpu v3 similar to cpu v1?
Contributor guide
Research direction
Reproduce the issue with the shown t.c source using clang --target=bpf at -O2 for mcpu=v1 and mcpu=v3, then compare the reported stack usage. Start with the SelectionDAG instruction-selection and scheduler output using -mllvm -debug-only=isel. Done means the v3 compilation no longer creates unnecessary large stack usage or rejects this case under the kernel limit.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100