Index: src/IceTargetLoweringX8632.cpp |
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp |
index 7edb2c36f92fb2e7b5c1c62811f2feca6829daa2..a1ba9d60088fb774394bbce8982fc0bff5baa8a2 100644 |
--- a/src/IceTargetLoweringX8632.cpp |
+++ b/src/IceTargetLoweringX8632.cpp |
@@ -883,7 +883,7 @@ void TargetX8632::addProlog(CfgNode *Node) { |
// that stack slot. |
if (SpillVariable *SpillVar = llvm::dyn_cast<SpillVariable>(Var)) { |
assert(Var->getWeight().isZero()); |
- if (!SpillVar->getLinkedTo()->hasReg()) { |
+ if (SpillVar->getLinkedTo() && !SpillVar->getLinkedTo()->hasReg()) { |
VariablesLinkedToSpillSlots.push_back(Var); |
continue; |
} |
@@ -1160,8 +1160,9 @@ void TargetX8632::split64(Variable *Var) { |
} |
Operand *TargetX8632::loOperand(Operand *Operand) { |
- assert(Operand->getType() == IceType_i64); |
- if (Operand->getType() != IceType_i64) |
+ assert(Operand->getType() == IceType_i64 || |
+ Operand->getType() == IceType_f64); |
+ if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) |
return Operand; |
if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
split64(Var); |
@@ -1180,8 +1181,9 @@ Operand *TargetX8632::loOperand(Operand *Operand) { |
} |
Operand *TargetX8632::hiOperand(Operand *Operand) { |
- assert(Operand->getType() == IceType_i64); |
- if (Operand->getType() != IceType_i64) |
+ assert(Operand->getType() == IceType_i64 || |
+ Operand->getType() == IceType_f64); |
+ if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) |
return Operand; |
if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
split64(Var); |
@@ -2463,20 +2465,25 @@ void TargetX8632::lowerCast(const InstCast *Inst) { |
// a_lo.i32 = t_lo.i32 |
// t_hi.i32 = hi(s.f64) |
// a_hi.i32 = t_hi.i32 |
- SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(IceType_f64); |
- SpillVar->setLinkedTo(llvm::dyn_cast<Variable>(Src0RM)); |
- Variable *Spill = SpillVar; |
- Spill->setWeight(RegWeight::Zero); |
- _movq(Spill, Src0RM); |
+ Operand *SpillLo, *SpillHi; |
+ if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0RM)) { |
+ SpillVariable *SpillVar = |
+ Func->makeVariable<SpillVariable>(IceType_f64); |
+ SpillVar->setLinkedTo(Src0Var); |
+ Variable *Spill = SpillVar; |
+ Spill->setWeight(RegWeight::Zero); |
+ _movq(Spill, Src0RM); |
+ SpillLo = VariableSplit::create(Func, Spill, VariableSplit::Low); |
+ SpillHi = VariableSplit::create(Func, Spill, VariableSplit::High); |
+ } else { |
+ SpillLo = loOperand(Src0RM); |
+ SpillHi = hiOperand(Src0RM); |
+ } |
Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
Variable *T_Lo = makeReg(IceType_i32); |
Variable *T_Hi = makeReg(IceType_i32); |
- VariableSplit *SpillLo = |
- VariableSplit::create(Func, Spill, VariableSplit::Low); |
- VariableSplit *SpillHi = |
- VariableSplit::create(Func, Spill, VariableSplit::High); |
_mov(T_Lo, SpillLo); |
_mov(DestLo, T_Lo); |
@@ -2486,6 +2493,12 @@ void TargetX8632::lowerCast(const InstCast *Inst) { |
case IceType_f64: { |
Src0 = legalize(Src0); |
assert(Src0->getType() == IceType_i64); |
+ if (llvm::isa<OperandX8632Mem>(Src0)) { |
+ Variable *T = Func->makeVariable(Dest->getType()); |
+ _movq(T, Src0); |
+ _movq(Dest, T); |
+ break; |
+ } |
// a.f64 = bitcast b.i64 ==> |
// t_lo.i32 = b_lo.i32 |
// FakeDef(s.f64) |
@@ -3955,20 +3968,23 @@ void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, |
} // anonymous namespace |
-void TargetX8632::lowerLoad(const InstLoad *Inst) { |
+void TargetX8632::lowerLoad(const InstLoad *Load) { |
// A Load instruction can be treated the same as an Assign |
// instruction, after the source operand is transformed into an |
// OperandX8632Mem operand. Note that the address mode |
// optimization already creates an OperandX8632Mem operand, so it |
// doesn't need another level of transformation. |
- Type Ty = Inst->getDest()->getType(); |
- Operand *Src0 = FormMemoryOperand(Inst->getSourceAddress(), Ty); |
+ Type Ty = Load->getDest()->getType(); |
+ Operand *Src0 = FormMemoryOperand(Load->getSourceAddress(), Ty); |
// Fuse this load with a subsequent Arithmetic instruction in the |
// following situations: |
// a=[mem]; c=b+a ==> c=b+[mem] if last use of a and a not in b |
// a=[mem]; c=a+b ==> c=b+[mem] if commutative and above is true |
// |
+ // Fuse this load with a subsequent Cast instruction: |
+ // a=[mem]; b=cast(a) ==> b=cast([mem]) if last use of a |
+ // |
// TODO: Clean up and test thoroughly. |
// (E.g., if there is an mfence-all make sure the load ends up on the |
// same side of the fence). |
@@ -3979,30 +3995,46 @@ void TargetX8632::lowerLoad(const InstLoad *Inst) { |
// load instruction's dest variable, and that instruction ends that |
// variable's live range, then make the substitution. Deal with |
// commutativity optimization in the arithmetic instruction lowering. |
- InstArithmetic *NewArith = nullptr; |
- if (InstArithmetic *Arith = |
- llvm::dyn_cast_or_null<InstArithmetic>(Context.getNextInst())) { |
- Variable *DestLoad = Inst->getDest(); |
- Variable *Src0Arith = llvm::dyn_cast<Variable>(Arith->getSrc(0)); |
- Variable *Src1Arith = llvm::dyn_cast<Variable>(Arith->getSrc(1)); |
- if (Src1Arith == DestLoad && Arith->isLastUse(Src1Arith) && |
- DestLoad != Src0Arith) { |
- NewArith = InstArithmetic::create(Func, Arith->getOp(), Arith->getDest(), |
- Arith->getSrc(0), Src0); |
- } else if (Src0Arith == DestLoad && Arith->isCommutative() && |
- Arith->isLastUse(Src0Arith) && DestLoad != Src1Arith) { |
- NewArith = InstArithmetic::create(Func, Arith->getOp(), Arith->getDest(), |
- Arith->getSrc(1), Src0); |
- } |
- if (NewArith) { |
- Arith->setDeleted(); |
- Context.advanceNext(); |
- lowerArithmetic(NewArith); |
- return; |
+ // |
+ // TODO(stichnot): Do load fusing as a separate pass. Run it before |
+ // the bool folding pass. Modify Ice::Inst to allow src operands to |
+ // be replaced, including updating Inst::LiveRangesEnded, to avoid |
+ // having to manually mostly clone each instruction type. |
+ Inst *NextInst = Context.getNextInst(); |
+ Variable *DestLoad = Load->getDest(); |
+ if (NextInst && NextInst->isLastUse(DestLoad)) { |
+ if (auto *Arith = llvm::dyn_cast<InstArithmetic>(NextInst)) { |
+ InstArithmetic *NewArith = nullptr; |
+ Variable *Src0Arith = llvm::dyn_cast<Variable>(Arith->getSrc(0)); |
+ Variable *Src1Arith = llvm::dyn_cast<Variable>(Arith->getSrc(1)); |
+ if (Src1Arith == DestLoad && DestLoad != Src0Arith) { |
+ NewArith = InstArithmetic::create( |
+ Func, Arith->getOp(), Arith->getDest(), Arith->getSrc(0), Src0); |
+ } else if (Src0Arith == DestLoad && Arith->isCommutative() && |
+ DestLoad != Src1Arith) { |
+ NewArith = InstArithmetic::create( |
+ Func, Arith->getOp(), Arith->getDest(), Arith->getSrc(1), Src0); |
+ } |
+ if (NewArith) { |
+ Arith->setDeleted(); |
+ Context.advanceNext(); |
+ lowerArithmetic(NewArith); |
+ return; |
+ } |
+ } else if (auto *Cast = llvm::dyn_cast<InstCast>(NextInst)) { |
+ Variable *Src0Cast = llvm::dyn_cast<Variable>(Cast->getSrc(0)); |
+ if (Src0Cast == DestLoad) { |
+ InstCast *NewCast = |
+ InstCast::create(Func, Cast->getCastKind(), Cast->getDest(), Src0); |
+ Cast->setDeleted(); |
+ Context.advanceNext(); |
+ lowerCast(NewCast); |
+ return; |
+ } |
} |
} |
- InstAssign *Assign = InstAssign::create(Func, Inst->getDest(), Src0); |
+ InstAssign *Assign = InstAssign::create(Func, DestLoad, Src0); |
lowerAssign(Assign); |
} |