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