aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Target/TargetLowering.h10
-rw-r--r--include/llvm/TargetTransformInfo.h7
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp6
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp51
-rw-r--r--lib/Target/ARM/ARMISelLowering.h13
-rw-r--r--lib/Target/ARM/ARMTargetMachine.h4
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,