Commit 5bc44313 by Jim Stichnoth

Subzero: Fix a register allocation issue for "advanced phi lowering".

When the advanced phi lowering handles a phi arg that is Undef, it lowers it to an assignment of a constant zero (or vector of zeroes). The ad-hoc register allocation was missing the fact that a vector of zeroes is done with "pxor %reg, %reg". This resulted in a pxor instruction with invalid addressing modes at emission time. The fix is to tell legalize() to use the dest physical register if dest has one; and if dest lacks a register, take the path where it actually does the ad-hoc register allocation as though the source operand were a memory operand. Tests are added for these vector undef phi args, and for scalar undef phi args as well for good measure. BUG= none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/969703002
parent e837e1a3
...@@ -1691,10 +1691,19 @@ void TargetX8632::lowerAssign(const InstAssign *Inst) { ...@@ -1691,10 +1691,19 @@ void TargetX8632::lowerAssign(const InstAssign *Inst) {
_mov(T_Hi, Src0Hi); _mov(T_Hi, Src0Hi);
_mov(DestHi, T_Hi); _mov(DestHi, T_Hi);
} else { } else {
// If Dest is in memory, then RI is either a physical register or Operand *RI;
// an immediate, otherwise RI can be anything. if (Dest->hasReg())
Operand *RI = // If Dest already has a physical register, then legalize the
legalize(Src0, Dest->hasReg() ? Legal_All : Legal_Reg | Legal_Imm); // Src operand into a Variable with the same register
// assignment. This is mostly a workaround for advanced phi
// lowering's ad-hoc register allocation which assumes no
// register allocation is needed when at least one of the
// operands is non-memory.
RI = legalize(Src0, Legal_Reg, Dest->getRegNum());
else
// If Dest could be a stack operand, then RI must be a physical
// register or a scalar integer immediate.
RI = legalize(Src0, Legal_Reg | Legal_Imm);
if (isVectorType(Dest->getType())) if (isVectorType(Dest->getType()))
_movp(Dest, RI); _movp(Dest, RI);
else else
...@@ -4163,6 +4172,12 @@ namespace { ...@@ -4163,6 +4172,12 @@ namespace {
bool isMemoryOperand(const Operand *Opnd) { bool isMemoryOperand(const Operand *Opnd) {
if (const auto Var = llvm::dyn_cast<Variable>(Opnd)) if (const auto Var = llvm::dyn_cast<Variable>(Opnd))
return !Var->hasReg(); return !Var->hasReg();
// We treat vector undef values the same as a memory operand,
// because they do in fact need a register to materialize the vector
// of zeroes into.
if (llvm::isa<ConstantUndef>(Opnd))
return isScalarFloatingType(Opnd->getType()) ||
isVectorType(Opnd->getType());
if (llvm::isa<Constant>(Opnd)) if (llvm::isa<Constant>(Opnd))
return isScalarFloatingType(Opnd->getType()); return isScalarFloatingType(Opnd->getType());
return true; return true;
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 --phi-edge-split=0 \ ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 --phi-edge-split=0 \
; RUN: | FileCheck %s ; RUN: | FileCheck %s
; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 --phi-edge-split=1 \
; RUN: | FileCheck --check-prefix=SPLIT %s
define internal i32 @testPhi1(i32 %arg) { define internal i32 @testPhi1(i32 %arg) {
entry: entry:
...@@ -99,3 +101,59 @@ exit: ...@@ -99,3 +101,59 @@ exit:
; CHECK: jne ; CHECK: jne
; CHECK: mov DWORD PTR [[ADDR]] ; CHECK: mov DWORD PTR [[ADDR]]
; CHECK: pop [[EBX]] ; CHECK: pop [[EBX]]
; Test of "advanced phi lowering" with undef phi arg (integer vector).
define internal <4 x i32> @test_split_undef_int_vec(<4 x i32> %arg, i32 %cond) {
entry:
%cmp = icmp eq i32 %cond, 0
br i1 %cmp, label %eq, label %exit
eq:
br label %exit
exit:
%merge = phi <4 x i32> [ %arg, %entry ], [ undef, %eq ]
ret <4 x i32> %merge
}
; SPLIT-LABEL: test_split_undef_int_vec
; SPLIT: pxor
; Test of "advanced phi lowering" with undef phi arg (float vector).
define internal <4 x float> @test_split_undef_float_vec(<4 x float> %arg, i32 %cond) {
entry:
%cmp = icmp eq i32 %cond, 0
br i1 %cmp, label %eq, label %exit
eq:
br label %exit
exit:
%merge = phi <4 x float> [ %arg, %entry ], [ undef, %eq ]
ret <4 x float> %merge
}
; SPLIT-LABEL: test_split_undef_float_vec
; SPLIT: pxor
; Test of "advanced phi lowering" with undef phi arg (integer scalar).
define internal i32 @test_split_undef_int_scalar(i32 %arg, i32 %cond) {
entry:
%cmp = icmp eq i32 %cond, 0
br i1 %cmp, label %eq, label %exit
eq:
br label %exit
exit:
%merge = phi i32 [ %arg, %entry ], [ undef, %eq ]
ret i32 %merge
}
; SPLIT-LABEL: test_split_undef_int_scalar
; SPLIT: mov {{.*}},0x0
; Test of "advanced phi lowering" with undef phi arg (float scalar).
define internal float @test_split_undef_float_scalar(float %arg, i32 %cond) {
entry:
%cmp = icmp eq i32 %cond, 0
br i1 %cmp, label %eq, label %exit
eq:
br label %exit
exit:
%merge = phi float [ %arg, %entry ], [ undef, %eq ]
ret float %merge
}
; SPLIT-LABEL: test_split_undef_float_scalar
; SPLIT: movss {{.*}},DWORD PTR
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