| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringX86Base.h - x86 lowering ----*- C++ -*-===// | 1 //===- subzero/src/IceTargetLoweringX86Base.h - x86 lowering ----*- C++ -*-===// |
| 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 declares the TargetLoweringX86 template class, which | 10 /// \file |
| 11 // implements the TargetLowering base interface for the x86 | 11 /// This file declares the TargetLoweringX86 template class, which |
| 12 // architecture. | 12 /// implements the TargetLowering base interface for the x86 |
| 13 // | 13 /// architecture. |
| 14 /// |
| 14 //===----------------------------------------------------------------------===// | 15 //===----------------------------------------------------------------------===// |
| 15 | 16 |
| 16 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H | 17 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H |
| 17 #define SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H | 18 #define SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H |
| 18 | 19 |
| 19 #include "IceDefs.h" | 20 #include "IceDefs.h" |
| 20 #include "IceInst.h" | 21 #include "IceInst.h" |
| 21 #include "IceTargetLowering.h" | 22 #include "IceTargetLowering.h" |
| 22 | 23 |
| 23 #include <type_traits> | 24 #include <type_traits> |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 void emit(const ConstantUndef *C) const final; | 135 void emit(const ConstantUndef *C) const final; |
| 135 void emit(const ConstantInteger32 *C) const final; | 136 void emit(const ConstantInteger32 *C) const final; |
| 136 void emit(const ConstantInteger64 *C) const final; | 137 void emit(const ConstantInteger64 *C) const final; |
| 137 void emit(const ConstantFloat *C) const final; | 138 void emit(const ConstantFloat *C) const final; |
| 138 void emit(const ConstantDouble *C) const final; | 139 void emit(const ConstantDouble *C) const final; |
| 139 | 140 |
| 140 void lowerArguments() override; | 141 void lowerArguments() override; |
| 141 void initNodeForLowering(CfgNode *Node) override; | 142 void initNodeForLowering(CfgNode *Node) override; |
| 142 void addProlog(CfgNode *Node) override; | 143 void addProlog(CfgNode *Node) override; |
| 143 void addEpilog(CfgNode *Node) override; | 144 void addEpilog(CfgNode *Node) override; |
| 144 // Ensure that a 64-bit Variable has been split into 2 32-bit | 145 /// Ensure that a 64-bit Variable has been split into 2 32-bit |
| 145 // Variables, creating them if necessary. This is needed for all | 146 /// Variables, creating them if necessary. This is needed for all |
| 146 // I64 operations, and it is needed for pushing F64 arguments for | 147 /// I64 operations, and it is needed for pushing F64 arguments for |
| 147 // function calls using the 32-bit push instruction (though the | 148 /// function calls using the 32-bit push instruction (though the |
| 148 // latter could be done by directly writing to the stack). | 149 /// latter could be done by directly writing to the stack). |
| 149 void split64(Variable *Var); | 150 void split64(Variable *Var); |
| 150 Operand *loOperand(Operand *Operand); | 151 Operand *loOperand(Operand *Operand); |
| 151 Operand *hiOperand(Operand *Operand); | 152 Operand *hiOperand(Operand *Operand); |
| 152 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, | 153 void finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
| 153 size_t BasicFrameOffset, size_t &InArgsSizeBytes); | 154 size_t BasicFrameOffset, size_t &InArgsSizeBytes); |
| 154 typename Traits::Address | 155 typename Traits::Address |
| 155 stackVarToAsmOperand(const Variable *Var) const final; | 156 stackVarToAsmOperand(const Variable *Var) const final; |
| 156 | 157 |
| 157 typename Traits::InstructionSet getInstructionSet() const final { | 158 typename Traits::InstructionSet getInstructionSet() const final { |
| 158 return InstructionSet; | 159 return InstructionSet; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 183 void lowerUnreachable(const InstUnreachable *Inst) override; | 184 void lowerUnreachable(const InstUnreachable *Inst) override; |
| 184 void lowerOther(const Inst *Instr) override; | 185 void lowerOther(const Inst *Instr) override; |
| 185 void lowerRMW(const InstX8632FakeRMW *RMW); | 186 void lowerRMW(const InstX8632FakeRMW *RMW); |
| 186 void prelowerPhis() override; | 187 void prelowerPhis() override; |
| 187 void lowerPhiAssignments(CfgNode *Node, | 188 void lowerPhiAssignments(CfgNode *Node, |
| 188 const AssignList &Assignments) override; | 189 const AssignList &Assignments) override; |
| 189 void doAddressOptLoad() override; | 190 void doAddressOptLoad() override; |
| 190 void doAddressOptStore() override; | 191 void doAddressOptStore() override; |
| 191 void randomlyInsertNop(float Probability) override; | 192 void randomlyInsertNop(float Probability) override; |
| 192 | 193 |
| 193 // Naive lowering of cmpxchg. | 194 /// Naive lowering of cmpxchg. |
| 194 void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected, | 195 void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected, |
| 195 Operand *Desired); | 196 Operand *Desired); |
| 196 // Attempt a more optimized lowering of cmpxchg. Returns true if optimized. | 197 /// Attempt a more optimized lowering of cmpxchg. Returns true if optimized. |
| 197 bool tryOptimizedCmpxchgCmpBr(Variable *DestPrev, Operand *Ptr, | 198 bool tryOptimizedCmpxchgCmpBr(Variable *DestPrev, Operand *Ptr, |
| 198 Operand *Expected, Operand *Desired); | 199 Operand *Expected, Operand *Desired); |
| 199 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, | 200 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, |
| 200 Operand *Val); | 201 Operand *Val); |
| 201 void lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, Operand *FirstVal, | 202 void lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, Operand *FirstVal, |
| 202 Operand *SecondVal); | 203 Operand *SecondVal); |
| 203 | 204 |
| 204 typedef void (TargetX86Base::*LowerBinOp)(Variable *, Operand *); | 205 typedef void (TargetX86Base::*LowerBinOp)(Variable *, Operand *); |
| 205 void expandAtomicRMWAsCmpxchg(LowerBinOp op_lo, LowerBinOp op_hi, | 206 void expandAtomicRMWAsCmpxchg(LowerBinOp op_lo, LowerBinOp op_hi, |
| 206 Variable *Dest, Operand *Ptr, Operand *Val); | 207 Variable *Dest, Operand *Ptr, Operand *Val); |
| 207 | 208 |
| 208 void eliminateNextVectorSextInstruction(Variable *SignExtendedResult); | 209 void eliminateNextVectorSextInstruction(Variable *SignExtendedResult); |
| 209 | 210 |
| 210 void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest, | 211 void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest, |
| 211 Operand *Src0, Operand *Src1); | 212 Operand *Src0, Operand *Src1); |
| 212 | 213 |
| 213 // Operand legalization helpers. To deal with address mode | 214 /// Operand legalization helpers. To deal with address mode |
| 214 // constraints, the helpers will create a new Operand and emit | 215 /// constraints, the helpers will create a new Operand and emit |
| 215 // instructions that guarantee that the Operand kind is one of those | 216 /// instructions that guarantee that the Operand kind is one of those |
| 216 // indicated by the LegalMask (a bitmask of allowed kinds). If the | 217 /// indicated by the LegalMask (a bitmask of allowed kinds). If the |
| 217 // input Operand is known to already meet the constraints, it may be | 218 /// input Operand is known to already meet the constraints, it may be |
| 218 // simply returned as the result, without creating any new | 219 /// simply returned as the result, without creating any new |
| 219 // instructions or operands. | 220 /// instructions or operands. |
| 220 enum OperandLegalization { | 221 enum OperandLegalization { |
| 221 Legal_None = 0, | 222 Legal_None = 0, |
| 222 Legal_Reg = 1 << 0, // physical register, not stack location | 223 Legal_Reg = 1 << 0, // physical register, not stack location |
| 223 Legal_Imm = 1 << 1, | 224 Legal_Imm = 1 << 1, |
| 224 Legal_Mem = 1 << 2, // includes [eax+4*ecx] as well as [esp+12] | 225 Legal_Mem = 1 << 2, // includes [eax+4*ecx] as well as [esp+12] |
| 225 Legal_All = ~Legal_None | 226 Legal_All = ~Legal_None |
| 226 }; | 227 }; |
| 227 typedef uint32_t LegalMask; | 228 typedef uint32_t LegalMask; |
| 228 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, | 229 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, |
| 229 int32_t RegNum = Variable::NoRegister); | 230 int32_t RegNum = Variable::NoRegister); |
| 230 Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister); | 231 Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister); |
| 231 // Legalize the first source operand for use in the cmp instruction. | 232 /// Legalize the first source operand for use in the cmp instruction. |
| 232 Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1); | 233 Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1); |
| 233 // Turn a pointer operand into a memory operand that can be | 234 /// Turn a pointer operand into a memory operand that can be |
| 234 // used by a real load/store operation. Legalizes the operand as well. | 235 /// used by a real load/store operation. Legalizes the operand as well. |
| 235 // This is a nop if the operand is already a legal memory operand. | 236 /// This is a nop if the operand is already a legal memory operand. |
| 236 OperandX8632Mem *formMemoryOperand(Operand *Ptr, Type Ty, | 237 OperandX8632Mem *formMemoryOperand(Operand *Ptr, Type Ty, |
| 237 bool DoLegalize = true); | 238 bool DoLegalize = true); |
| 238 | 239 |
| 239 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); | 240 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); |
| 240 static Type stackSlotType(); | 241 static Type stackSlotType(); |
| 241 | 242 |
| 242 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister); | 243 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister); |
| 243 | 244 |
| 244 // Returns a vector in a register with the given constant entries. | 245 /// Returns a vector in a register with the given constant entries. |
| 245 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister); | 246 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister); |
| 246 Variable *makeVectorOfOnes(Type Ty, int32_t RegNum = Variable::NoRegister); | 247 Variable *makeVectorOfOnes(Type Ty, int32_t RegNum = Variable::NoRegister); |
| 247 Variable *makeVectorOfMinusOnes(Type Ty, | 248 Variable *makeVectorOfMinusOnes(Type Ty, |
| 248 int32_t RegNum = Variable::NoRegister); | 249 int32_t RegNum = Variable::NoRegister); |
| 249 Variable *makeVectorOfHighOrderBits(Type Ty, | 250 Variable *makeVectorOfHighOrderBits(Type Ty, |
| 250 int32_t RegNum = Variable::NoRegister); | 251 int32_t RegNum = Variable::NoRegister); |
| 251 Variable *makeVectorOfFabsMask(Type Ty, | 252 Variable *makeVectorOfFabsMask(Type Ty, |
| 252 int32_t RegNum = Variable::NoRegister); | 253 int32_t RegNum = Variable::NoRegister); |
| 253 | 254 |
| 254 // Return a memory operand corresponding to a stack allocated Variable. | 255 /// Return a memory operand corresponding to a stack allocated Variable. |
| 255 OperandX8632Mem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot, | 256 OperandX8632Mem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot, |
| 256 uint32_t Offset = 0); | 257 uint32_t Offset = 0); |
| 257 | 258 |
| 258 void makeRandomRegisterPermutation( | 259 void makeRandomRegisterPermutation( |
| 259 llvm::SmallVectorImpl<int32_t> &Permutation, | 260 llvm::SmallVectorImpl<int32_t> &Permutation, |
| 260 const llvm::SmallBitVector &ExcludeRegisters) const override; | 261 const llvm::SmallBitVector &ExcludeRegisters) const override; |
| 261 | 262 |
| 262 // TODO(jpp): move the helper methods below to the MachineTraits. | 263 // TODO(jpp): move the helper methods below to the MachineTraits. |
| 263 // The following are helpers that insert lowered x86 instructions | 264 /// The following are helpers that insert lowered x86 instructions |
| 264 // with minimal syntactic overhead, so that the lowering code can | 265 /// with minimal syntactic overhead, so that the lowering code can |
| 265 // look as close to assembly as practical. | 266 /// look as close to assembly as practical. |
| 266 void _adc(Variable *Dest, Operand *Src0) { | 267 void _adc(Variable *Dest, Operand *Src0) { |
| 267 Context.insert(InstX8632Adc::create(Func, Dest, Src0)); | 268 Context.insert(InstX8632Adc::create(Func, Dest, Src0)); |
| 268 } | 269 } |
| 269 void _adc_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { | 270 void _adc_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { |
| 270 Context.insert(InstX8632AdcRMW::create(Func, DestSrc0, Src1)); | 271 Context.insert(InstX8632AdcRMW::create(Func, DestSrc0, Src1)); |
| 271 } | 272 } |
| 272 void _add(Variable *Dest, Operand *Src0) { | 273 void _add(Variable *Dest, Operand *Src0) { |
| 273 Context.insert(InstX8632Add::create(Func, Dest, Src0)); | 274 Context.insert(InstX8632Add::create(Func, Dest, Src0)); |
| 274 } | 275 } |
| 275 void _add_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { | 276 void _add_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 void _insertps(Variable *Dest, Operand *Src0, Operand *Src1) { | 379 void _insertps(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 379 Context.insert(InstX8632Insertps::create(Func, Dest, Src0, Src1)); | 380 Context.insert(InstX8632Insertps::create(Func, Dest, Src0, Src1)); |
| 380 } | 381 } |
| 381 void _jmp(Operand *Target) { | 382 void _jmp(Operand *Target) { |
| 382 Context.insert(InstX8632Jmp::create(Func, Target)); | 383 Context.insert(InstX8632Jmp::create(Func, Target)); |
| 383 } | 384 } |
| 384 void _lea(Variable *Dest, Operand *Src0) { | 385 void _lea(Variable *Dest, Operand *Src0) { |
| 385 Context.insert(InstX8632Lea::create(Func, Dest, Src0)); | 386 Context.insert(InstX8632Lea::create(Func, Dest, Src0)); |
| 386 } | 387 } |
| 387 void _mfence() { Context.insert(InstX8632Mfence::create(Func)); } | 388 void _mfence() { Context.insert(InstX8632Mfence::create(Func)); } |
| 388 // If Dest=nullptr is passed in, then a new variable is created, | 389 /// If Dest=nullptr is passed in, then a new variable is created, |
| 389 // marked as infinite register allocation weight, and returned | 390 /// marked as infinite register allocation weight, and returned |
| 390 // through the in/out Dest argument. | 391 /// through the in/out Dest argument. |
| 391 void _mov(Variable *&Dest, Operand *Src0, | 392 void _mov(Variable *&Dest, Operand *Src0, |
| 392 int32_t RegNum = Variable::NoRegister) { | 393 int32_t RegNum = Variable::NoRegister) { |
| 393 if (Dest == nullptr) | 394 if (Dest == nullptr) |
| 394 Dest = makeReg(Src0->getType(), RegNum); | 395 Dest = makeReg(Src0->getType(), RegNum); |
| 395 Context.insert(InstX8632Mov::create(Func, Dest, Src0)); | 396 Context.insert(InstX8632Mov::create(Func, Dest, Src0)); |
| 396 } | 397 } |
| 397 void _mov_nonkillable(Variable *Dest, Operand *Src0) { | 398 void _mov_nonkillable(Variable *Dest, Operand *Src0) { |
| 398 Inst *NewInst = InstX8632Mov::create(Func, Dest, Src0); | 399 Inst *NewInst = InstX8632Mov::create(Func, Dest, Src0); |
| 399 NewInst->setDestNonKillable(); | 400 NewInst->setDestNonKillable(); |
| 400 Context.insert(NewInst); | 401 Context.insert(NewInst); |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 Traits::InstructionSet::Begin; | 595 Traits::InstructionSet::Begin; |
| 595 bool IsEbpBasedFrame = false; | 596 bool IsEbpBasedFrame = false; |
| 596 bool NeedsStackAlignment = false; | 597 bool NeedsStackAlignment = false; |
| 597 size_t SpillAreaSizeBytes = 0; | 598 size_t SpillAreaSizeBytes = 0; |
| 598 llvm::SmallBitVector TypeToRegisterSet[IceType_NUM]; | 599 llvm::SmallBitVector TypeToRegisterSet[IceType_NUM]; |
| 599 llvm::SmallBitVector ScratchRegs; | 600 llvm::SmallBitVector ScratchRegs; |
| 600 llvm::SmallBitVector RegsUsed; | 601 llvm::SmallBitVector RegsUsed; |
| 601 VarList PhysicalRegisters[IceType_NUM]; | 602 VarList PhysicalRegisters[IceType_NUM]; |
| 602 static IceString RegNames[]; | 603 static IceString RegNames[]; |
| 603 | 604 |
| 604 // Randomize a given immediate operand | 605 /// Randomize a given immediate operand |
| 605 Operand *randomizeOrPoolImmediate(Constant *Immediate, | 606 Operand *randomizeOrPoolImmediate(Constant *Immediate, |
| 606 int32_t RegNum = Variable::NoRegister); | 607 int32_t RegNum = Variable::NoRegister); |
| 607 OperandX8632Mem * | 608 OperandX8632Mem * |
| 608 randomizeOrPoolImmediate(OperandX8632Mem *MemOperand, | 609 randomizeOrPoolImmediate(OperandX8632Mem *MemOperand, |
| 609 int32_t RegNum = Variable::NoRegister); | 610 int32_t RegNum = Variable::NoRegister); |
| 610 bool RandomizationPoolingPaused = false; | 611 bool RandomizationPoolingPaused = false; |
| 611 | 612 |
| 612 private: | 613 private: |
| 613 ~TargetX86Base() override {} | 614 ~TargetX86Base() override {} |
| 614 BoolFolding FoldingInfo; | 615 BoolFolding FoldingInfo; |
| 615 }; | 616 }; |
| 616 } // end of namespace X86Internal | 617 } // end of namespace X86Internal |
| 617 } // end of namespace Ice | 618 } // end of namespace Ice |
| 618 | 619 |
| 619 #include "IceTargetLoweringX86BaseImpl.h" | 620 #include "IceTargetLoweringX86BaseImpl.h" |
| 620 | 621 |
| 621 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H | 622 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H |
| OLD | NEW |