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 |
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 // |
| 3985 // Fuse this load with a subsequent Cast instruction: |
| 3986 // a=[mem]; b=cast(a) ==> b=cast([mem]) if last use of a |
| 3987 // |
3972 // TODO: Clean up and test thoroughly. | 3988 // TODO: Clean up and test thoroughly. |
3973 // (E.g., if there is an mfence-all make sure the load ends up on the | 3989 // (E.g., if there is an mfence-all make sure the load ends up on the |
3974 // same side of the fence). | 3990 // same side of the fence). |
3975 // | 3991 // |
3976 // TODO: Why limit to Arithmetic instructions? This could probably be | 3992 // TODO: Why limit to Arithmetic instructions? This could probably be |
3977 // applied to most any instruction type. Look at all source operands | 3993 // applied to most any instruction type. Look at all source operands |
3978 // in the following instruction, and if there is one instance of the | 3994 // in the following instruction, and if there is one instance of the |
3979 // load instruction's dest variable, and that instruction ends that | 3995 // load instruction's dest variable, and that instruction ends that |
3980 // variable's live range, then make the substitution. Deal with | 3996 // variable's live range, then make the substitution. Deal with |
3981 // commutativity optimization in the arithmetic instruction lowering. | 3997 // commutativity optimization in the arithmetic instruction lowering. |
3982 InstArithmetic *NewArith = nullptr; | 3998 // |
3983 if (InstArithmetic *Arith = | 3999 // TODO(stichnot): Do load fusing as a separate pass. Run it before |
3984 llvm::dyn_cast_or_null<InstArithmetic>(Context.getNextInst())) { | 4000 // the bool folding pass. Modify Ice::Inst to allow src operands to |
3985 Variable *DestLoad = Inst->getDest(); | 4001 // be replaced, including updating Inst::LiveRangesEnded, to avoid |
3986 Variable *Src0Arith = llvm::dyn_cast<Variable>(Arith->getSrc(0)); | 4002 // having to manually mostly clone each instruction type. |
3987 Variable *Src1Arith = llvm::dyn_cast<Variable>(Arith->getSrc(1)); | 4003 Inst *NextInst = Context.getNextInst(); |
3988 if (Src1Arith == DestLoad && Arith->isLastUse(Src1Arith) && | 4004 Variable *DestLoad = Load->getDest(); |
3989 DestLoad != Src0Arith) { | 4005 if (NextInst && NextInst->isLastUse(DestLoad)) { |
3990 NewArith = InstArithmetic::create(Func, Arith->getOp(), Arith->getDest(), | 4006 if (auto *Arith = llvm::dyn_cast<InstArithmetic>(NextInst)) { |
3991 Arith->getSrc(0), Src0); | 4007 InstArithmetic *NewArith = nullptr; |
3992 } else if (Src0Arith == DestLoad && Arith->isCommutative() && | 4008 Variable *Src0Arith = llvm::dyn_cast<Variable>(Arith->getSrc(0)); |
3993 Arith->isLastUse(Src0Arith) && DestLoad != Src1Arith) { | 4009 Variable *Src1Arith = llvm::dyn_cast<Variable>(Arith->getSrc(1)); |
3994 NewArith = InstArithmetic::create(Func, Arith->getOp(), Arith->getDest(), | 4010 if (Src1Arith == DestLoad && DestLoad != Src0Arith) { |
3995 Arith->getSrc(1), Src0); | 4011 NewArith = InstArithmetic::create( |
3996 } | 4012 Func, Arith->getOp(), Arith->getDest(), Arith->getSrc(0), Src0); |
3997 if (NewArith) { | 4013 } else if (Src0Arith == DestLoad && Arith->isCommutative() && |
3998 Arith->setDeleted(); | 4014 DestLoad != Src1Arith) { |
3999 Context.advanceNext(); | 4015 NewArith = InstArithmetic::create( |
4000 lowerArithmetic(NewArith); | 4016 Func, Arith->getOp(), Arith->getDest(), Arith->getSrc(1), Src0); |
4001 return; | 4017 } |
| 4018 if (NewArith) { |
| 4019 Arith->setDeleted(); |
| 4020 Context.advanceNext(); |
| 4021 lowerArithmetic(NewArith); |
| 4022 return; |
| 4023 } |
| 4024 } else if (auto *Cast = llvm::dyn_cast<InstCast>(NextInst)) { |
| 4025 Variable *Src0Cast = llvm::dyn_cast<Variable>(Cast->getSrc(0)); |
| 4026 if (Src0Cast == DestLoad) { |
| 4027 InstCast *NewCast = |
| 4028 InstCast::create(Func, Cast->getCastKind(), Cast->getDest(), Src0); |
| 4029 Cast->setDeleted(); |
| 4030 Context.advanceNext(); |
| 4031 lowerCast(NewCast); |
| 4032 return; |
| 4033 } |
4002 } | 4034 } |
4003 } | 4035 } |
4004 | 4036 |
4005 InstAssign *Assign = InstAssign::create(Func, Inst->getDest(), Src0); | 4037 InstAssign *Assign = InstAssign::create(Func, DestLoad, Src0); |
4006 lowerAssign(Assign); | 4038 lowerAssign(Assign); |
4007 } | 4039 } |
4008 | 4040 |
4009 void TargetX8632::doAddressOptLoad() { | 4041 void TargetX8632::doAddressOptLoad() { |
4010 Inst *Inst = Context.getCur(); | 4042 Inst *Inst = Context.getCur(); |
4011 Variable *Dest = Inst->getDest(); | 4043 Variable *Dest = Inst->getDest(); |
4012 Operand *Addr = Inst->getSrc(0); | 4044 Operand *Addr = Inst->getSrc(0); |
4013 Variable *Index = nullptr; | 4045 Variable *Index = nullptr; |
4014 uint16_t Shift = 0; | 4046 uint16_t Shift = 0; |
4015 int32_t Offset = 0; // TODO: make Constant | 4047 int32_t Offset = 0; // TODO: make Constant |
(...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5032 case FT_Asm: | 5064 case FT_Asm: |
5033 case FT_Iasm: { | 5065 case FT_Iasm: { |
5034 OstreamLocker L(Ctx); | 5066 OstreamLocker L(Ctx); |
5035 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 5067 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
5036 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 5068 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
5037 } break; | 5069 } break; |
5038 } | 5070 } |
5039 } | 5071 } |
5040 | 5072 |
5041 } // end of namespace Ice | 5073 } // end of namespace Ice |
OLD | NEW |