Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit cc64dc6

Browse files
author
Jim Grosbach
committed
X86 fast-isel: Avoid explicit AH subreg reference for [SU]Rem.
Explicit references to %AH for an i8 remainder instruction can lead to references to %AH in a REX prefixed instruction, which causes things to blow up. Do the same thing in FastISel as we do for DAG isel and instead shift %AX right by 8 bits and then extract the 8-bit subreg from that result. rdar://14203849 http://llvm.org/bugs/show_bug.cgi?id=16105 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185899 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 845e196 commit cc64dc6

File tree

1 file changed

+31
-4
lines changed

1 file changed

+31
-4
lines changed

lib/Target/X86/X86FastISel.cpp

+31-4
Original file line numberDiff line numberDiff line change
@@ -1376,10 +1376,37 @@ bool X86FastISel::X86SelectDivRem(const Instruction *I) {
13761376
// Generate the DIV/IDIV instruction.
13771377
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
13781378
TII.get(OpEntry.OpDivRem)).addReg(Op1Reg);
1379-
// Copy output register into result register.
1380-
unsigned ResultReg = createResultReg(TypeEntry.RC);
1381-
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
1382-
TII.get(Copy), ResultReg).addReg(OpEntry.DivRemResultReg);
1379+
// For i8 remainder, we can't reference AH directly, as we'll end
1380+
// up with bogus copies like %R9B = COPY %AH. Reference AX
1381+
// instead to prevent AH references in a REX instruction.
1382+
//
1383+
// The current assumption of the fast register allocator is that isel
1384+
// won't generate explicit references to the GPR8_NOREX registers. If
1385+
// the allocator and/or the backend get enhanced to be more robust in
1386+
// that regard, this can be, and should be, removed.
1387+
unsigned ResultReg = 0;
1388+
if ((I->getOpcode() == Instruction::SRem ||
1389+
I->getOpcode() == Instruction::URem) &&
1390+
OpEntry.DivRemResultReg == X86::AH && Subtarget->is64Bit()) {
1391+
unsigned SourceSuperReg = createResultReg(&X86::GR16RegClass);
1392+
unsigned ResultSuperReg = createResultReg(&X86::GR16RegClass);
1393+
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
1394+
TII.get(Copy), SourceSuperReg).addReg(X86::AX);
1395+
1396+
// Shift AX right by 8 bits instead of using AH.
1397+
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::SHR16ri),
1398+
ResultSuperReg).addReg(SourceSuperReg).addImm(8);
1399+
1400+
// Now reference the 8-bit subreg of the result.
1401+
ResultReg = FastEmitInst_extractsubreg(MVT::i8, ResultSuperReg,
1402+
/*Kill=*/true, X86::sub_8bit);
1403+
}
1404+
// Copy the result out of the physreg if we haven't already.
1405+
if (!ResultReg) {
1406+
ResultReg = createResultReg(TypeEntry.RC);
1407+
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Copy), ResultReg)
1408+
.addReg(OpEntry.DivRemResultReg);
1409+
}
13831410
UpdateValueMap(I, ResultReg);
13841411

13851412
return true;

0 commit comments

Comments
 (0)