diff options
-rw-r--r-- | include/llvm/Target/TargetLowering.h | 10 | ||||
-rw-r--r-- | include/llvm/TargetTransformInfo.h | 7 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 6 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.cpp | 51 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelLowering.h | 13 | ||||
-rw-r--r-- | lib/Target/ARM/ARMTargetMachine.h | 4 |
6 files changed, 58 insertions, 33 deletions
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index d2e20107ef..faf0a0179a 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -371,16 +371,6 @@ public: return false; } - /// isIntImmLegal - Returns true if the target can instruction select the - /// specified integer immediate natively (that is, it's materialized with one - /// instruction). The current *assumption* in isel is all of integer - /// immediates are "legal" and only the memcpy / memset expansion code is - /// making use of this. The rest of isel doesn't have proper cost model for - /// immediate materialization. - virtual bool isIntImmLegal(const APInt &/*Imm*/, EVT /*VT*/) const { - return true; - } - /// isShuffleMaskLegal - Targets can use this to indicate that they only /// support *some* VECTOR_SHUFFLE operations, those with specific masks. /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values diff --git a/include/llvm/TargetTransformInfo.h b/include/llvm/TargetTransformInfo.h index 519ccb9263..59fcf3b785 100644 --- a/include/llvm/TargetTransformInfo.h +++ b/include/llvm/TargetTransformInfo.h @@ -140,6 +140,13 @@ public: virtual PopcntHwSupport getPopcntHwSupport(unsigned IntTyWidthInBit) const { return None; } + + /// getIntImmCost - Return the expected cost of materializing the given + /// integer immediate of the specified type. + virtual unsigned getIntImmCost(const APInt&, Type*) const { + // Default assumption is immediate is cheap. + return 1; + } }; /// VectorTargetTransformInfo - This interface is used by the vectorizers diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 29339405aa..4cb63ce9a6 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -41,6 +41,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetTransformInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetIntrinsicInfo.h" #include "llvm/Target/TargetLowering.h" @@ -3382,7 +3383,10 @@ static SDValue getMemsetStringVal(EVT VT, DebugLoc dl, SelectionDAG &DAG, Val |= (uint64_t)(unsigned char)Str[i] << (NumVTBytes-i-1)*8; } - if (TLI.isIntImmLegal(Val, VT)) + // If the "cost" of materializing the integer immediate is 1 or free, then + // it is cost effective to turn the load into the immediate. + if (DAG.getTarget().getScalarTargetTransformInfo()-> + getIntImmCost(Val, VT.getTypeForEVT(*DAG.getContext())) < 2) return DAG.getConstant(Val, VT); return SDValue(0, 0); } diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 474eb32d39..88282c7331 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -10260,24 +10260,6 @@ bool ARMTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { return false; } -bool ARMTargetLowering::isIntImmLegal(const APInt &Imm, EVT VT) const { - if (VT.getSizeInBits() > 32) - return false; - - int32_t ImmVal = Imm.getSExtValue(); - if (!Subtarget->isThumb()) { - return (ImmVal >= 0 && ImmVal < 65536) || - (ARM_AM::getSOImmVal(ImmVal) != -1) || - (ARM_AM::getSOImmVal(~ImmVal) != -1); - } else if (Subtarget->isThumb2()) { - return (ImmVal >= 0 && ImmVal < 65536) || - (ARM_AM::getT2SOImmVal(ImmVal) != -1) || - (ARM_AM::getT2SOImmVal(~ImmVal) != -1); - } else /*Thumb1*/ { - return (ImmVal >= 0 && ImmVal < 256); - } -} - /// getTgtMemIntrinsic - Represent NEON load and store intrinsics as /// MemIntrinsicNodes. The associated MachineMemOperands record the alignment /// specified in the intrinsic calls. @@ -10359,3 +10341,36 @@ bool ARMTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, return false; } + +unsigned +ARMScalarTargetTransformImpl::getIntImmCost(const APInt &Imm, Type *Ty) const { + assert(Ty->isIntegerTy()); + + unsigned Bits = Ty->getPrimitiveSizeInBits(); + if (Bits == 0 || Bits > 32) + return 4; + + int32_t SImmVal = Imm.getSExtValue(); + uint32_t ZImmVal = Imm.getZExtValue(); + if (!Subtarget->isThumb()) { + if ((SImmVal >= 0 && SImmVal < 65536) || + (ARM_AM::getSOImmVal(ZImmVal) != -1) || + (ARM_AM::getSOImmVal(~ZImmVal) != -1)) + return 1; + return Subtarget->hasV6T2Ops() ? 2 : 3; + } else if (Subtarget->isThumb2()) { + if ((SImmVal >= 0 && SImmVal < 65536) || + (ARM_AM::getT2SOImmVal(ZImmVal) != -1) || + (ARM_AM::getT2SOImmVal(~ZImmVal) != -1)) + return 1; + return Subtarget->hasV6T2Ops() ? 2 : 3; + } else /*Thumb1*/ { + if (SImmVal >= 0 && SImmVal < 256) + return 1; + if ((~ZImmVal < 256) || ARM_AM::isThumbImmShiftedVal(ZImmVal)) + return 2; + // Load from constantpool. + return 3; + } + return 2; +} diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index 5cf40236c5..5a44201ec4 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -22,6 +22,7 @@ #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetTransformImpl.h" #include <vector> namespace llvm { @@ -387,8 +388,6 @@ namespace llvm { /// materialize the FP immediate as a load from a constant pool. virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const; - virtual bool isIntImmLegal(const APInt &Imm, EVT VT) const; - virtual bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, unsigned Intrinsic) const; @@ -575,6 +574,16 @@ namespace llvm { FastISel *createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo); } + + class ARMScalarTargetTransformImpl : public ScalarTargetTransformImpl { + const ARMSubtarget *Subtarget; + public: + explicit ARMScalarTargetTransformImpl(const TargetLowering *TL) : + ScalarTargetTransformImpl(TL), + Subtarget(&TL->getTargetMachine().getSubtarget<ARMSubtarget>()) {}; + + virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; + }; } #endif // ARMISELLOWERING_H diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h index 834eb3c66a..6f5f50d3c6 100644 --- a/lib/Target/ARM/ARMTargetMachine.h +++ b/lib/Target/ARM/ARMTargetMachine.h @@ -66,7 +66,7 @@ class ARMTargetMachine : public ARMBaseTargetMachine { ARMTargetLowering TLInfo; ARMSelectionDAGInfo TSInfo; ARMFrameLowering FrameLowering; - ScalarTargetTransformImpl STTI; + ARMScalarTargetTransformImpl STTI; VectorTargetTransformImpl VTTI; public: ARMTargetMachine(const Target &T, StringRef TT, @@ -112,7 +112,7 @@ class ThumbTargetMachine : public ARMBaseTargetMachine { ARMSelectionDAGInfo TSInfo; // Either Thumb1FrameLowering or ARMFrameLowering. OwningPtr<ARMFrameLowering> FrameLowering; - ScalarTargetTransformImpl STTI; + ARMScalarTargetTransformImpl STTI; VectorTargetTransformImpl VTTI; public: ThumbTargetMachine(const Target &T, StringRef TT, |