diff --git a/bolt/lib/Passes/RegReAssign.cpp b/bolt/lib/Passes/RegReAssign.cpp --- a/bolt/lib/Passes/RegReAssign.cpp +++ b/bolt/lib/Passes/RegReAssign.cpp @@ -175,9 +175,25 @@ continue; // Disallow substituitions involving regs in instrs that cannot use REX + // The relationship of X86 registers is shown in the diagram. BL and BH + // do not have a direct alias relationship. However, if the BH register + // cannot be swapped, then the BX/EBX/RBX registers cannot be swapped as + // well, which means that BL register also cannot be swapped. Therefore, + // in the presence of BX/EBX/RBX registers, BL and BH have an alias + // relationship. + // ┌─────────────────┐ + // │ RBX │ + // ├─────┬───────────┤ + // │ │ EBX │ + // ├─────┴──┬────────┤ + // │ │ BX │ + // ├────────┼───┬────┤ + // │ │BH │BL │ + // └────────┴───┴────┘ if (CannotUseREX) { RegScore[RegEC] = std::numeric_limits::min(); + RegScore[BC.MIB->getAliasSized(Reg, 1)] = RegScore[RegEC]; continue; } @@ -185,6 +201,7 @@ if (BC.MIB->isUpper8BitReg(Reg) && ClassicCSR.test(Reg)) { RegScore[RegEC] = std::numeric_limits::min(); + RegScore[BC.MIB->getAliasSized(Reg, 1)] = RegScore[RegEC]; continue; } @@ -370,6 +387,15 @@ if (!RBX) return false; + // The high 8 bits of the register will never be swapped. To prevent the high + // 8 bits from being swapped incorrectly, we should switched to swapping the + // low 8 bits of the register instead. + if (BC.MIB->isUpper8BitReg(RBX)) { + RBX = BC.MIB->getAliasSized(RBX, 1); + if (RegScore[RBX] < 0 || RegScore[RBX] > RegScore[Candidate]) + return false; + } + LLVM_DEBUG(dbgs() << "\n ** Swapping " << BC.MRI->getName(RBX) << " with " << BC.MRI->getName(Candidate) << "\n\n"); (void)BC; diff --git a/bolt/test/runtime/X86/reg-reassign-no-swap-bl.s b/bolt/test/runtime/X86/reg-reassign-no-swap-bl.s new file mode 100644 --- /dev/null +++ b/bolt/test/runtime/X86/reg-reassign-no-swap-bl.s @@ -0,0 +1,59 @@ +# This test case is used to reproduce an issue found in the mongod database. +# In function rankRegisters, if there is a BH Reg in the basic block, then the BL Reg +# also cannot be swap. + +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: link_fdata %s %t.o %t.fdata +# RUN: llvm-strip --strip-unneeded %t.o +# RUN: %clang -no-pie %t.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.out -data=%t.fdata --reg-reassign | FileCheck %s +# RUN: %t.out + +# CHECK: Reg Reassignment Pass: no changes were made + .text + .globl main + .globl main.cold + .p2align 4, 0x90 + .type main,@function + .type main.cold,@function +main.cold: +bb1: + mov $0x2, %bh +bb2: + jmp bb5 +main: # @main + .cfi_startproc +# %bb.0: # %entry + pushq %rax + pushq %r12 + pushq %rbx + .cfi_def_cfa_offset 16 + mov $0x1, %r12 + shr $0x14, %r12 + add $0x14, %r12 + mov $0x11, %rbx + mov $0x1, %bh + mov $0x1, %bl +bb3: + add $0x1, %r12 +bb4: + jmp bb1 +bb5: + cmp $0x201, %rbx + jne 0x0 +bb6: + xorl %eax, %eax + popq %rcx + popq %rbx + popq %r12 + .cfi_def_cfa_offset 8 + retq +# FDATA: 1 main.cold #bb2# 1 main 0 0 100 +# FDATA: 1 main #bb3# 1 main #bb4# 0 100 +# FDATA: 1 main #bb4# 1 main.cold 0 0 100 + +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc