The fuzzer bugs #219 and #227 are both cases where the register allocator coloring pass "runs out of registers". What's really happening is that the constraint solver failed to find a solution, even when one existed. Suppose we have three solver variables: v0(GPR, out, global) v1(GPR, in) v2(GPR, in, out) And suppose registers %r0 and %r1 are available on both input and output sides of the instruction, but only %r1 is available for global outputs. A valid solution would be: v0 -> %r1 v1 -> %r1 v2 -> %r0 However, the solver would pick registers for the three values in numerical order because v1 and v2 have the same domain size (=2). This would assign v1 -> %r0 and then fail to find a free register for v2. Fix this by prioritizing in+out variables over single-sided variables even when their domains are equal. This means the v2 gets assigned a register before v1, and it gets a chance to pick a register that is still available on both in and out sides. Also try to avoid depending on value numbers in the solver. These bugs were hard to reproduce because a test case invariably would have different value numbers, causing the solver to order its variables differently and succeed. Throw in the previous solution and original register assignments as tie breakers which are stable and not dependent on value numbers. This is still not a substitute for a proper solver search algorithm that we will probably have to write eventually. Fixes #219 Fixes #227
102 lines
4.4 KiB
Plaintext
102 lines
4.4 KiB
Plaintext
test regalloc
|
|
set is_64bit
|
|
isa intel haswell
|
|
|
|
function %pr227(i32 [%rdi], i32 [%rsi], i32 [%rdx], i32 [%rcx], i64 vmctx [%r8]) native {
|
|
gv0 = vmctx
|
|
heap0 = static gv0, min 0, bound 0x0001_0000_0000, guard 0x8000_0000
|
|
|
|
ebb0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i64):
|
|
@0001 [RexOp1puid#b8] v5 = iconst.i32 0
|
|
@0003 [RexOp1puid#b8] v6 = iconst.i32 0
|
|
@0005 [RexOp1tjccb#74] brz v6, ebb10
|
|
@0007 [RexOp1jmpb#eb] jump ebb3(v5, v5, v5, v5, v5, v5, v0, v1, v2, v3)
|
|
|
|
ebb3(v15: i32, v17: i32, v25: i32, v31: i32, v40: i32, v47: i32, v54: i32, v61: i32, v68: i32, v75: i32):
|
|
@000b [RexOp1jmpb#eb] jump ebb6
|
|
|
|
ebb6:
|
|
@000d [RexOp1puid#b8] v8 = iconst.i32 0
|
|
@000f [RexOp1tjccb#75] brnz v8, ebb5
|
|
@0011 [RexOp1puid#b8] v9 = iconst.i32 0
|
|
@0015 [RexOp1puid#b8] v11 = iconst.i32 0
|
|
@0017 [RexOp1icscc#39] v12 = icmp.i32 eq v15, v11
|
|
@0017 [RexOp2urm#4b6] v13 = bint.i32 v12
|
|
@001a [RexOp1rr#21] v14 = band v9, v13
|
|
@001b [RexOp1tjccb#75] brnz v14, ebb6
|
|
@001d [RexOp1jmpb#eb] jump ebb7
|
|
|
|
ebb7:
|
|
@0020 [RexOp1tjccb#74] brz.i32 v17, ebb8
|
|
@0022 [RexOp1puid#b8] v18 = iconst.i32 0
|
|
@0024 [RexOp1tjccb#74] brz v18, ebb9
|
|
@0028 [RexOp1puid#b8] v21 = iconst.i32 0
|
|
@002a [RexOp1umr#89] v79 = uextend.i64 v5
|
|
@002a [RexOp1rib#8083] v80 = iadd_imm.i64 v4, 0
|
|
@002a [RexOp1ld#808b] v81 = load.i64 v80
|
|
@002a [RexOp1rr#8001] v22 = iadd v81, v79
|
|
@002a [RexMp1st#189] istore16 v21, v22
|
|
@002d [RexOp1jmpb#eb] jump ebb9
|
|
|
|
ebb9:
|
|
@002e [RexOp1jmpb#eb] jump ebb8
|
|
|
|
ebb8:
|
|
@0033 [RexOp1puid#b8] v27 = iconst.i32 3
|
|
@0035 [RexOp1puid#b8] v28 = iconst.i32 4
|
|
@003b [RexOp1rr#09] v35 = bor.i32 v31, v13
|
|
@003c [RexOp1tjccb#75] brnz v35, ebb15(v27)
|
|
@003c [RexOp1jmpb#eb] jump ebb15(v28)
|
|
|
|
ebb15(v36: i32):
|
|
@003f [RexOp1jmpb#eb] jump ebb3(v25, v36, v25, v31, v40, v47, v54, v61, v68, v75)
|
|
|
|
ebb5:
|
|
@0042 [RexOp1jmpb#eb] jump ebb4
|
|
|
|
ebb4:
|
|
@0045 [RexOp1jmpb#eb] jump ebb2(v40, v47, v54, v61, v68, v75)
|
|
|
|
ebb10:
|
|
@0046 [RexOp1puid#b8] v43 = iconst.i32 0
|
|
@0048 [RexOp1jmpb#eb] jump ebb2(v43, v5, v0, v1, v2, v3)
|
|
|
|
ebb2(v7: i32, v45: i32, v52: i32, v59: i32, v66: i32, v73: i32):
|
|
@004c [RexOp1puid#b8] v44 = iconst.i32 0
|
|
@004e [RexOp1tjccb#74] brz v44, ebb12
|
|
@0052 [RexOp1puid#b8] v50 = iconst.i32 11
|
|
@0054 [RexOp1tjccb#74] brz v50, ebb14
|
|
@0058 [RexOp1umr#89] v82 = uextend.i64 v52
|
|
@0058 [RexOp1rib#8083] v83 = iadd_imm.i64 v4, 0
|
|
@0058 [RexOp1ld#808b] v84 = load.i64 v83
|
|
@0058 [RexOp1rr#8001] v57 = iadd v84, v82
|
|
@0058 [RexOp1ld#8b] v58 = load.i32 v57
|
|
@005d [RexOp1umr#89] v85 = uextend.i64 v58
|
|
@005d [RexOp1rib#8083] v86 = iadd_imm.i64 v4, 0
|
|
@005d [RexOp1ld#808b] v87 = load.i64 v86
|
|
@005d [RexOp1rr#8001] v64 = iadd v87, v85
|
|
@005d [RexOp1st#88] istore8 v59, v64
|
|
@0060 [RexOp1puid#b8] v65 = iconst.i32 0
|
|
@0062 [RexOp1jmpb#eb] jump ebb13(v65)
|
|
|
|
ebb14:
|
|
@0065 [RexOp1jmpb#eb] jump ebb13(v66)
|
|
|
|
ebb13(v51: i32):
|
|
@0066 [RexOp1umr#89] v88 = uextend.i64 v45
|
|
@0066 [RexOp1rib#8083] v89 = iadd_imm.i64 v4, 0
|
|
@0066 [RexOp1ld#808b] v90 = load.i64 v89
|
|
@0066 [RexOp1rr#8001] v71 = iadd v90, v88
|
|
@0066 [RexOp1st#89] store v51, v71
|
|
@0069 [RexOp1jmpb#eb] jump ebb12
|
|
|
|
ebb12:
|
|
@006a [RexOp1jmpb#eb] jump ebb11
|
|
|
|
ebb11:
|
|
@006e [RexOp1jmpb#eb] jump ebb1
|
|
|
|
ebb1:
|
|
@006e [Op1ret#c3] return
|
|
}
|