Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file implements the TargetLoweringX8632 class, which | 10 // This file implements the TargetLoweringX8632 class, which |
| (...skipping 865 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 876 // register) or already has one (if passed on the stack). | 876 // register) or already has one (if passed on the stack). |
| 877 if (Var->getIsArg()) | 877 if (Var->getIsArg()) |
| 878 continue; | 878 continue; |
| 879 // An unreferenced variable doesn't need a stack slot. | 879 // An unreferenced variable doesn't need a stack slot. |
| 880 if (!IsVarReferenced[Var->getIndex()]) | 880 if (!IsVarReferenced[Var->getIndex()]) |
| 881 continue; | 881 continue; |
| 882 // A spill slot linked to a variable with a stack slot should reuse | 882 // A spill slot linked to a variable with a stack slot should reuse |
| 883 // that stack slot. | 883 // that stack slot. |
| 884 if (SpillVariable *SpillVar = llvm::dyn_cast<SpillVariable>(Var)) { | 884 if (SpillVariable *SpillVar = llvm::dyn_cast<SpillVariable>(Var)) { |
| 885 assert(Var->getWeight().isZero()); | 885 assert(Var->getWeight().isZero()); |
| 886 if (!SpillVar->getLinkedTo()->hasReg()) { | 886 if (SpillVar->getLinkedTo() && !SpillVar->getLinkedTo()->hasReg()) { |
| 887 VariablesLinkedToSpillSlots.push_back(Var); | 887 VariablesLinkedToSpillSlots.push_back(Var); |
| 888 continue; | 888 continue; |
| 889 } | 889 } |
| 890 } | 890 } |
| 891 SpilledVariables.push_back(Var); | 891 SpilledVariables.push_back(Var); |
| 892 } | 892 } |
| 893 | 893 |
| 894 SortedSpilledVariables.reserve(SpilledVariables.size()); | 894 SortedSpilledVariables.reserve(SpilledVariables.size()); |
| 895 sortByAlignment(SortedSpilledVariables, SpilledVariables); | 895 sortByAlignment(SortedSpilledVariables, SpilledVariables); |
| 896 for (Variable *Var : SortedSpilledVariables) { | 896 for (Variable *Var : SortedSpilledVariables) { |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1153 Hi->setName(Func, Var->getName(Func) + "__hi"); | 1153 Hi->setName(Func, Var->getName(Func) + "__hi"); |
| 1154 } | 1154 } |
| 1155 Var->setLoHi(Lo, Hi); | 1155 Var->setLoHi(Lo, Hi); |
| 1156 if (Var->getIsArg()) { | 1156 if (Var->getIsArg()) { |
| 1157 Lo->setIsArg(); | 1157 Lo->setIsArg(); |
| 1158 Hi->setIsArg(); | 1158 Hi->setIsArg(); |
| 1159 } | 1159 } |
| 1160 } | 1160 } |
| 1161 | 1161 |
| 1162 Operand *TargetX8632::loOperand(Operand *Operand) { | 1162 Operand *TargetX8632::loOperand(Operand *Operand) { |
| 1163 assert(Operand->getType() == IceType_i64); | 1163 assert(Operand->getType() == IceType_i64 || |
| 1164 if (Operand->getType() != IceType_i64) | 1164 Operand->getType() == IceType_f64); |
| 1165 if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) | |
| 1165 return Operand; | 1166 return Operand; |
| 1166 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | 1167 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
| 1167 split64(Var); | 1168 split64(Var); |
| 1168 return Var->getLo(); | 1169 return Var->getLo(); |
| 1169 } | 1170 } |
| 1170 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 1171 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 1171 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); | 1172 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); |
| 1172 } | 1173 } |
| 1173 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { | 1174 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
| 1174 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), | 1175 return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), |
| 1175 Mem->getOffset(), Mem->getIndex(), | 1176 Mem->getOffset(), Mem->getIndex(), |
| 1176 Mem->getShift(), Mem->getSegmentRegister()); | 1177 Mem->getShift(), Mem->getSegmentRegister()); |
| 1177 } | 1178 } |
| 1178 llvm_unreachable("Unsupported operand type"); | 1179 llvm_unreachable("Unsupported operand type"); |
| 1179 return nullptr; | 1180 return nullptr; |
| 1180 } | 1181 } |
| 1181 | 1182 |
| 1182 Operand *TargetX8632::hiOperand(Operand *Operand) { | 1183 Operand *TargetX8632::hiOperand(Operand *Operand) { |
| 1183 assert(Operand->getType() == IceType_i64); | 1184 assert(Operand->getType() == IceType_i64 || |
| 1184 if (Operand->getType() != IceType_i64) | 1185 Operand->getType() == IceType_f64); |
| 1186 if (Operand->getType() != IceType_i64 && Operand->getType() != IceType_f64) | |
| 1185 return Operand; | 1187 return Operand; |
| 1186 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | 1188 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
| 1187 split64(Var); | 1189 split64(Var); |
| 1188 return Var->getHi(); | 1190 return Var->getHi(); |
| 1189 } | 1191 } |
| 1190 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 1192 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| 1191 return Ctx->getConstantInt32( | 1193 return Ctx->getConstantInt32( |
| 1192 static_cast<uint32_t>(Const->getValue() >> 32)); | 1194 static_cast<uint32_t>(Const->getValue() >> 32)); |
| 1193 } | 1195 } |
| 1194 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { | 1196 if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
| (...skipping 1261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2456 } break; | 2458 } break; |
| 2457 case IceType_i64: { | 2459 case IceType_i64: { |
| 2458 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 2460 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
| 2459 assert(Src0RM->getType() == IceType_f64); | 2461 assert(Src0RM->getType() == IceType_f64); |
| 2460 // a.i64 = bitcast b.f64 ==> | 2462 // a.i64 = bitcast b.f64 ==> |
| 2461 // s.f64 = spill b.f64 | 2463 // s.f64 = spill b.f64 |
| 2462 // t_lo.i32 = lo(s.f64) | 2464 // t_lo.i32 = lo(s.f64) |
| 2463 // a_lo.i32 = t_lo.i32 | 2465 // a_lo.i32 = t_lo.i32 |
| 2464 // t_hi.i32 = hi(s.f64) | 2466 // t_hi.i32 = hi(s.f64) |
| 2465 // a_hi.i32 = t_hi.i32 | 2467 // a_hi.i32 = t_hi.i32 |
| 2466 SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(IceType_f64); | 2468 Operand *SpillLo, *SpillHi; |
| 2467 SpillVar->setLinkedTo(llvm::dyn_cast<Variable>(Src0RM)); | 2469 if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0RM)) { |
| 2468 Variable *Spill = SpillVar; | 2470 SpillVariable *SpillVar = |
| 2469 Spill->setWeight(RegWeight::Zero); | 2471 Func->makeVariable<SpillVariable>(IceType_f64); |
| 2470 _movq(Spill, Src0RM); | 2472 SpillVar->setLinkedTo(Src0Var); |
| 2473 Variable *Spill = SpillVar; | |
| 2474 Spill->setWeight(RegWeight::Zero); | |
| 2475 _movq(Spill, Src0RM); | |
| 2476 SpillLo = VariableSplit::create(Func, Spill, VariableSplit::Low); | |
| 2477 SpillHi = VariableSplit::create(Func, Spill, VariableSplit::High); | |
| 2478 } else { | |
| 2479 SpillLo = loOperand(Src0RM); | |
| 2480 SpillHi = hiOperand(Src0RM); | |
| 2481 } | |
| 2471 | 2482 |
| 2472 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2483 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2473 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2484 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2474 Variable *T_Lo = makeReg(IceType_i32); | 2485 Variable *T_Lo = makeReg(IceType_i32); |
| 2475 Variable *T_Hi = makeReg(IceType_i32); | 2486 Variable *T_Hi = makeReg(IceType_i32); |
| 2476 VariableSplit *SpillLo = | |
| 2477 VariableSplit::create(Func, Spill, VariableSplit::Low); | |
| 2478 VariableSplit *SpillHi = | |
| 2479 VariableSplit::create(Func, Spill, VariableSplit::High); | |
| 2480 | 2487 |
| 2481 _mov(T_Lo, SpillLo); | 2488 _mov(T_Lo, SpillLo); |
| 2482 _mov(DestLo, T_Lo); | 2489 _mov(DestLo, T_Lo); |
| 2483 _mov(T_Hi, SpillHi); | 2490 _mov(T_Hi, SpillHi); |
| 2484 _mov(DestHi, T_Hi); | 2491 _mov(DestHi, T_Hi); |
| 2485 } break; | 2492 } break; |
| 2486 case IceType_f64: { | 2493 case IceType_f64: { |
| 2487 Src0 = legalize(Src0); | 2494 Src0 = legalize(Src0); |
| 2488 assert(Src0->getType() == IceType_i64); | 2495 assert(Src0->getType() == IceType_i64); |
| 2496 if (llvm::isa<OperandX8632Mem>(Src0)) { | |
| 2497 Variable *T = Func->makeVariable(Dest->getType()); | |
| 2498 _movq(T, Src0); | |
| 2499 _movq(Dest, T); | |
| 2500 break; | |
| 2501 } | |
| 2489 // a.f64 = bitcast b.i64 ==> | 2502 // a.f64 = bitcast b.i64 ==> |
| 2490 // t_lo.i32 = b_lo.i32 | 2503 // t_lo.i32 = b_lo.i32 |
| 2491 // FakeDef(s.f64) | 2504 // FakeDef(s.f64) |
| 2492 // lo(s.f64) = t_lo.i32 | 2505 // lo(s.f64) = t_lo.i32 |
| 2493 // t_hi.i32 = b_hi.i32 | 2506 // t_hi.i32 = b_hi.i32 |
| 2494 // hi(s.f64) = t_hi.i32 | 2507 // hi(s.f64) = t_hi.i32 |
| 2495 // a.f64 = s.f64 | 2508 // a.f64 = s.f64 |
| 2496 SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(IceType_f64); | 2509 SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(IceType_f64); |
| 2497 SpillVar->setLinkedTo(Dest); | 2510 SpillVar->setLinkedTo(Dest); |
| 2498 Variable *Spill = SpillVar; | 2511 Variable *Spill = SpillVar; |
| (...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3948 // Index is Index=Var-Const ==> | 3961 // Index is Index=Var-Const ==> |
| 3949 // set Index=Var, Offset-=(Const<<Shift) | 3962 // set Index=Var, Offset-=(Const<<Shift) |
| 3950 | 3963 |
| 3951 // TODO: consider overflow issues with respect to Offset. | 3964 // TODO: consider overflow issues with respect to Offset. |
| 3952 // TODO: handle symbolic constants. | 3965 // TODO: handle symbolic constants. |
| 3953 } | 3966 } |
| 3954 } | 3967 } |
| 3955 | 3968 |
| 3956 } // anonymous namespace | 3969 } // anonymous namespace |
| 3957 | 3970 |
| 3958 void TargetX8632::lowerLoad(const InstLoad *Inst) { | 3971 void TargetX8632::lowerLoad(const InstLoad *Load) { |
| 3959 // A Load instruction can be treated the same as an Assign | 3972 // A Load instruction can be treated the same as an Assign |
| 3960 // instruction, after the source operand is transformed into an | 3973 // instruction, after the source operand is transformed into an |
| 3961 // OperandX8632Mem operand. Note that the address mode | 3974 // OperandX8632Mem operand. Note that the address mode |
| 3962 // optimization already creates an OperandX8632Mem operand, so it | 3975 // optimization already creates an OperandX8632Mem operand, so it |
| 3963 // doesn't need another level of transformation. | 3976 // doesn't need another level of transformation. |
| 3964 Type Ty = Inst->getDest()->getType(); | 3977 Type Ty = Load->getDest()->getType(); |
| 3965 Operand *Src0 = FormMemoryOperand(Inst->getSourceAddress(), Ty); | 3978 Operand *Src0 = FormMemoryOperand(Load->getSourceAddress(), Ty); |
| 3966 | 3979 |
| 3967 // Fuse this load with a subsequent Arithmetic instruction in the | 3980 // Fuse this load with a subsequent Arithmetic instruction in the |
|
jvoung (off chromium)
2015/05/31 17:27:56
"Fuse ... Arithmetic or Cast..." but may need to r
Jim Stichnoth
2015/06/01 06:35:12
Added a separate description for Cast.
| |
| 3968 // following situations: | 3981 // following situations: |
| 3969 // a=[mem]; c=b+a ==> c=b+[mem] if last use of a and a not in b | 3982 // a=[mem]; c=b+a ==> c=b+[mem] if last use of a and a not in b |
| 3970 // a=[mem]; c=a+b ==> c=b+[mem] if commutative and above is true | 3983 // a=[mem]; c=a+b ==> c=b+[mem] if commutative and above is true |
| 3971 // | 3984 // |
| 3972 // TODO: Clean up and test thoroughly. | 3985 // TODO: Clean up and test thoroughly. |
| 3973 // (E.g., if there is an mfence-all make sure the load ends up on the | 3986 // (E.g., if there is an mfence-all make sure the load ends up on the |
| 3974 // same side of the fence). | 3987 // same side of the fence). |
| 3975 // | 3988 // |
| 3976 // TODO: Why limit to Arithmetic instructions? This could probably be | 3989 // TODO: Why limit to Arithmetic instructions? This could probably be |
| 3977 // applied to most any instruction type. Look at all source operands | 3990 // applied to most any instruction type. Look at all source operands |
| 3978 // in the following instruction, and if there is one instance of the | 3991 // in the following instruction, and if there is one instance of the |
| 3979 // load instruction's dest variable, and that instruction ends that | 3992 // load instruction's dest variable, and that instruction ends that |
| 3980 // variable's live range, then make the substitution. Deal with | 3993 // variable's live range, then make the substitution. Deal with |
| 3981 // commutativity optimization in the arithmetic instruction lowering. | 3994 // commutativity optimization in the arithmetic instruction lowering. |
| 3982 InstArithmetic *NewArith = nullptr; | 3995 // |
| 3983 if (InstArithmetic *Arith = | 3996 // TODO(stichnot): Do load fusing as a separate pass. Run it before |
| 3984 llvm::dyn_cast_or_null<InstArithmetic>(Context.getNextInst())) { | 3997 // the bool folding pass. Modify Ice::Inst to allow src operands to |
| 3985 Variable *DestLoad = Inst->getDest(); | 3998 // be replaced, including updating Inst::LiveRangesEnded, to avoid |
| 3986 Variable *Src0Arith = llvm::dyn_cast<Variable>(Arith->getSrc(0)); | 3999 // having to manually mostly clone each instruction type. |
| 3987 Variable *Src1Arith = llvm::dyn_cast<Variable>(Arith->getSrc(1)); | 4000 Inst *NextInst = Context.getNextInst(); |
| 3988 if (Src1Arith == DestLoad && Arith->isLastUse(Src1Arith) && | 4001 Variable *DestLoad = Load->getDest(); |
| 3989 DestLoad != Src0Arith) { | 4002 if (NextInst && NextInst->isLastUse(DestLoad)) { |
| 3990 NewArith = InstArithmetic::create(Func, Arith->getOp(), Arith->getDest(), | 4003 if (auto *Arith = llvm::dyn_cast<InstArithmetic>(NextInst)) { |
| 3991 Arith->getSrc(0), Src0); | 4004 InstArithmetic *NewArith = nullptr; |
| 3992 } else if (Src0Arith == DestLoad && Arith->isCommutative() && | 4005 Variable *Src0Arith = llvm::dyn_cast<Variable>(Arith->getSrc(0)); |
| 3993 Arith->isLastUse(Src0Arith) && DestLoad != Src1Arith) { | 4006 Variable *Src1Arith = llvm::dyn_cast<Variable>(Arith->getSrc(1)); |
| 3994 NewArith = InstArithmetic::create(Func, Arith->getOp(), Arith->getDest(), | 4007 if (Src1Arith == DestLoad && DestLoad != Src0Arith) { |
| 3995 Arith->getSrc(1), Src0); | 4008 NewArith = InstArithmetic::create( |
| 3996 } | 4009 Func, Arith->getOp(), Arith->getDest(), Arith->getSrc(0), Src0); |
| 3997 if (NewArith) { | 4010 } else if (Src0Arith == DestLoad && Arith->isCommutative() && |
| 3998 Arith->setDeleted(); | 4011 DestLoad != Src1Arith) { |
| 3999 Context.advanceNext(); | 4012 NewArith = InstArithmetic::create( |
| 4000 lowerArithmetic(NewArith); | 4013 Func, Arith->getOp(), Arith->getDest(), Arith->getSrc(1), Src0); |
| 4001 return; | 4014 } |
| 4015 if (NewArith) { | |
| 4016 Arith->setDeleted(); | |
| 4017 Context.advanceNext(); | |
| 4018 lowerArithmetic(NewArith); | |
| 4019 return; | |
| 4020 } | |
| 4021 } else if (auto *Cast = llvm::dyn_cast<InstCast>(NextInst)) { | |
| 4022 Variable *Src0Cast = llvm::dyn_cast<Variable>(Cast->getSrc(0)); | |
| 4023 if (Src0Cast == DestLoad) { | |
| 4024 InstCast *NewCast = | |
| 4025 InstCast::create(Func, Cast->getCastKind(), Cast->getDest(), Src0); | |
| 4026 Cast->setDeleted(); | |
| 4027 Context.advanceNext(); | |
| 4028 lowerCast(NewCast); | |
| 4029 return; | |
| 4030 } | |
| 4002 } | 4031 } |
| 4003 } | 4032 } |
| 4004 | 4033 |
| 4005 InstAssign *Assign = InstAssign::create(Func, Inst->getDest(), Src0); | 4034 InstAssign *Assign = InstAssign::create(Func, DestLoad, Src0); |
| 4006 lowerAssign(Assign); | 4035 lowerAssign(Assign); |
| 4007 } | 4036 } |
| 4008 | 4037 |
| 4009 void TargetX8632::doAddressOptLoad() { | 4038 void TargetX8632::doAddressOptLoad() { |
| 4010 Inst *Inst = Context.getCur(); | 4039 Inst *Inst = Context.getCur(); |
| 4011 Variable *Dest = Inst->getDest(); | 4040 Variable *Dest = Inst->getDest(); |
| 4012 Operand *Addr = Inst->getSrc(0); | 4041 Operand *Addr = Inst->getSrc(0); |
| 4013 Variable *Index = nullptr; | 4042 Variable *Index = nullptr; |
| 4014 uint16_t Shift = 0; | 4043 uint16_t Shift = 0; |
| 4015 int32_t Offset = 0; // TODO: make Constant | 4044 int32_t Offset = 0; // TODO: make Constant |
| (...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5032 case FT_Asm: | 5061 case FT_Asm: |
| 5033 case FT_Iasm: { | 5062 case FT_Iasm: { |
| 5034 OstreamLocker L(Ctx); | 5063 OstreamLocker L(Ctx); |
| 5035 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 5064 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
| 5036 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 5065 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
| 5037 } break; | 5066 } break; |
| 5038 } | 5067 } |
| 5039 } | 5068 } |
| 5040 | 5069 |
| 5041 } // end of namespace Ice | 5070 } // end of namespace Ice |
| OLD | NEW |