From 38b67d0cafd5bfb2465bd290b0e9dba699ec2bdd Mon Sep 17 00:00:00 2001 From: Juergen Ributzka Date: Fri, 24 Jan 2014 18:23:08 +0000 Subject: Add Constant Hoisting Pass This pass identifies expensive constants to hoist and coalesces them to better prepare it for SelectionDAG-based code generation. This works around the limitations of the basic-block-at-a-time approach. First it scans all instructions for integer constants and calculates its cost. If the constant can be folded into the instruction (the cost is TCC_Free) or the cost is just a simple operation (TCC_BASIC), then we don't consider it expensive and leave it alone. This is the default behavior and the default implementation of getIntImmCost will always return TCC_Free. If the cost is more than TCC_BASIC, then the integer constant can't be folded into the instruction and it might be beneficial to hoist the constant. Similar constants are coalesced to reduce register pressure and materialization code. When a constant is hoisted, it is also hidden behind a bitcast to force it to be live-out of the basic block. Otherwise the constant would be just duplicated and each basic block would have its own copy in the SelectionDAG. The SelectionDAG recognizes such constants as opaque and doesn't perform certain transformations on them, which would create a new expensive constant. This optimization is only applied to integer constants in instructions and simple (this means not nested) constant cast experessions. For example: %0 = load i64* inttoptr (i64 big_constant to i64*) Reviewed by Eric llvm-svn: 200022 --- llvm/lib/Target/X86/X86TargetTransformInfo.cpp | 95 ++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) (limited to 'llvm/lib/Target') diff --git a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp index da2b021da93..781be2fddd9 100644 --- a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp +++ b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp @@ -18,6 +18,7 @@ #include "X86.h" #include "X86TargetMachine.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/Support/Debug.h" #include "llvm/Target/CostTable.h" #include "llvm/Target/TargetLowering.h" @@ -107,6 +108,14 @@ public: virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, bool IsPairwiseForm) const LLVM_OVERRIDE; + virtual unsigned getIntImmCost(const APInt &Imm, + Type *Ty) const LLVM_OVERRIDE; + + virtual unsigned getIntImmCost(unsigned Opcode, const APInt &Imm, + Type *Ty) const LLVM_OVERRIDE; + virtual unsigned getIntImmCost(Intrinsic::ID IID, const APInt &Imm, + Type *Ty) const LLVM_OVERRIDE; + /// @} }; @@ -694,3 +703,89 @@ unsigned X86TTI::getReductionCost(unsigned Opcode, Type *ValTy, return TargetTransformInfo::getReductionCost(Opcode, ValTy, IsPairwise); } +unsigned X86TTI::getIntImmCost(const APInt &Imm, Type *Ty) const { + assert(Ty->isIntegerTy()); + + unsigned BitSize = Ty->getPrimitiveSizeInBits(); + if (BitSize == 0) + return ~0U; + + if (Imm.getBitWidth() <= 64 && + (isInt<32>(Imm.getSExtValue()) || isUInt<32>(Imm.getZExtValue()))) + return TCC_Basic; + else + return 2 * TCC_Basic; +} + +unsigned X86TTI::getIntImmCost(unsigned Opcode, const APInt &Imm, + Type *Ty) const { + assert(Ty->isIntegerTy()); + + unsigned BitSize = Ty->getPrimitiveSizeInBits(); + if (BitSize == 0) + return ~0U; + + switch (Opcode) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::URem: + case Instruction::SRem: + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + case Instruction::ICmp: + if (Imm.getBitWidth() <= 64 && isInt<32>(Imm.getSExtValue())) + return TCC_Free; + else + return X86TTI::getIntImmCost(Imm, Ty); + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::IntToPtr: + case Instruction::PtrToInt: + case Instruction::BitCast: + case Instruction::Call: + case Instruction::Select: + case Instruction::Ret: + case Instruction::Load: + case Instruction::Store: + return X86TTI::getIntImmCost(Imm, Ty); + } + return TargetTransformInfo::getIntImmCost(Opcode, Imm, Ty); +} + +unsigned X86TTI::getIntImmCost(Intrinsic::ID IID, const APInt &Imm, + Type *Ty) const { + assert(Ty->isIntegerTy()); + + unsigned BitSize = Ty->getPrimitiveSizeInBits(); + if (BitSize == 0) + return ~0U; + + switch (IID) { + default: return TargetTransformInfo::getIntImmCost(IID, Imm, Ty); + case Intrinsic::sadd_with_overflow: + case Intrinsic::uadd_with_overflow: + case Intrinsic::ssub_with_overflow: + case Intrinsic::usub_with_overflow: + case Intrinsic::smul_with_overflow: + case Intrinsic::umul_with_overflow: + if (Imm.getBitWidth() <= 64 && isInt<32>(Imm.getSExtValue())) + return TCC_Free; + else + return X86TTI::getIntImmCost(Imm, Ty); + case Intrinsic::experimental_stackmap: + case Intrinsic::experimental_patchpoint_void: + case Intrinsic::experimental_patchpoint_i64: + if (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue())) + return TCC_Free; + else + return X86TTI::getIntImmCost(Imm, Ty); + } +} -- cgit v1.2.3