Commit 017a5538 by Jim Stichnoth

Subzero: Fix lowering for x86 div/rem instructions.

The x86 lowering sequences for sdiv/udiv/srem/urem all have a problem, in that they don't reflect the fact that two registers are affected by the instruction. For example, the urem instruction: dest = src0 urem src1 lowers to something like this: t1:eax = src0 t2:edx = 0 t2:edx = (t1:eax and t2:edx) div src1 dest = t2:edx The problem is that there is no indication that the div instruction smashes eax. As such, it's possible that the register allocator could erroneously assume that src0 is still available in eax after the div instruction. To fix this, we make use of the FakeDef instruction. In this example, we change the div instruction to "officially" produce eax as its result, then fakedef edx in terms of eax. This means that as long as the urem result is actually used, the definitions of eax and edx will be preserved, but if the urem result is unused, then the whole sequence can be dead-code eliminated. t1:eax = src0 t2:edx = 0 t1:eax = (t1:eax and t2:edx) div src1 # dest var changed to t1:eax t2:edx = fakedef t1:eax # fakedef instruction added dest = t2:edx BUG= none R=jpp@chromium.org Review URL: https://codereview.chromium.org/2158213002 .
parent 5674c915
......@@ -2283,7 +2283,8 @@ void TargetX86Base<TraitsType>::lowerArithmetic(const InstArithmetic *Instr) {
T_edx = makeReg(Ty, Edx);
_mov(T, Src0, Eax);
_mov(T_edx, Ctx->getConstantZero(Ty));
_div(T, Src1, T_edx);
_div(T_edx, Src1, T);
_redefined(Context.insert<InstFakeDef>(T, T_edx));
_mov(Dest, T);
} break;
case InstArithmetic::Sdiv:
......@@ -2343,7 +2344,8 @@ void TargetX86Base<TraitsType>::lowerArithmetic(const InstArithmetic *Instr) {
break;
}
_cbwdq(T_edx, T);
_idiv(T, Src1, T_edx);
_idiv(T_edx, Src1, T);
_redefined(Context.insert<InstFakeDef>(T, T_edx));
_mov(Dest, T);
break;
case InstArithmetic::Urem: {
......@@ -2373,7 +2375,8 @@ void TargetX86Base<TraitsType>::lowerArithmetic(const InstArithmetic *Instr) {
T_edx = makeReg(Ty, Edx);
_mov(T_edx, Ctx->getConstantZero(Ty));
_mov(T, Src0, Eax);
_div(T_edx, Src1, T);
_div(T, Src1, T_edx);
_redefined(Context.insert<InstFakeDef>(T_edx, T));
if (Ty == IceType_i8) {
// Register ah must be moved into one of {al,bl,cl,dl} before it can be
// moved into a general 8-bit register.
......@@ -2450,7 +2453,8 @@ void TargetX86Base<TraitsType>::lowerArithmetic(const InstArithmetic *Instr) {
T_edx = makeReg(Ty, Edx);
_mov(T, Src0, Eax);
_cbwdq(T_edx, T);
_idiv(T_edx, Src1, T);
_idiv(T, Src1, T_edx);
_redefined(Context.insert<InstFakeDef>(T_edx, T));
if (Ty == IceType_i8) {
// Register ah must be moved into one of {al,bl,cl,dl} before it can be
// moved into a general 8-bit register.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment