Change allowsUnalignedMemoryAccesses to take type argument since some targets

support unaligned mem access only for certain types. (Should it be size
instead?)

ARM v7 supports unaligned access for i16 and i32, some v6 variants support it
as well.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79127 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng
2009-08-15 19:23:44 +00:00
parent e93f37350d
commit 088880cb19
7 changed files with 76 additions and 33 deletions

View File

@ -637,13 +637,13 @@ public:
unsigned getMaxStoresPerMemmove() const { return maxStoresPerMemmove; } unsigned getMaxStoresPerMemmove() const { return maxStoresPerMemmove; }
/// This function returns true if the target allows unaligned memory accesses. /// This function returns true if the target allows unaligned memory accesses.
/// This is used, for example, in situations where an array copy/move/set is /// of the specified type. This is used, for example, in situations where an
/// converted to a sequence of store operations. It's use helps to ensure that /// array copy/move/set is converted to a sequence of store operations. It's
/// such replacements don't generate code that causes an alignment error /// use helps to ensure that such replacements don't generate code that causes
/// (trap) on the target machine. /// an alignment error (trap) on the target machine.
/// @brief Determine if the target supports unaligned memory accesses. /// @brief Determine if the target supports unaligned memory accesses.
bool allowsUnalignedMemoryAccesses() const { virtual bool allowsUnalignedMemoryAccesses(EVT VT) const {
return allowUnalignedMemoryAccesses; return false;
} }
/// This function returns true if the target would benefit from code placement /// This function returns true if the target would benefit from code placement
@ -1757,12 +1757,6 @@ protected:
/// @brief Specify maximum bytes of store instructions per memmove call. /// @brief Specify maximum bytes of store instructions per memmove call.
unsigned maxStoresPerMemmove; unsigned maxStoresPerMemmove;
/// This field specifies whether the target machine permits unaligned memory
/// accesses. This is used, for example, to determine the size of store
/// operations when copying small arrays and other similar tasks.
/// @brief Indicate whether the target permits unaligned memory accesses.
bool allowUnalignedMemoryAccesses;
/// This field specifies whether the target can benefit from code placement /// This field specifies whether the target can benefit from code placement
/// optimization. /// optimization.
bool benefitFromCodePlacementOpt; bool benefitFromCodePlacementOpt;

View File

@ -3121,6 +3121,27 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N,
return SDValue(); return SDValue();
} }
bool ARMTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const {
if (!Subtarget->hasV6Ops())
// Pre-v6 does not support unaligned mem access.
return false;
else if (!Subtarget->hasV6Ops()) {
// v6 may or may not support unaligned mem access.
if (!Subtarget->isTargetDarwin())
return false;
}
switch (VT.getSimpleVT().SimpleTy) {
default:
return false;
case MVT::i8:
case MVT::i16:
case MVT::i32:
return true;
// FIXME: VLD1 etc with standard alignment is legal.
}
}
static bool isLegalT1AddressImmediate(int64_t V, EVT VT) { static bool isLegalT1AddressImmediate(int64_t V, EVT VT) {
if (V < 0) if (V < 0)
return false; return false;

View File

@ -166,6 +166,11 @@ namespace llvm {
virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *MBB) const; MachineBasicBlock *MBB) const;
/// allowsUnalignedMemoryAccesses - Returns true if the target allows
/// unaligned memory accesses. of the specified type.
/// FIXME: Add getOptimalMemOpType to implement memcpy with NEON?
virtual bool allowsUnalignedMemoryAccesses(EVT VT) const;
/// isLegalAddressingMode - Return true if the addressing mode represented /// isLegalAddressingMode - Return true if the addressing mode represented
/// by AM is legal for this target, for a load/store of the specified type. /// by AM is legal for this target, for a load/store of the specified type.
virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty)const; virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty)const;
@ -193,6 +198,8 @@ namespace llvm {
APInt &KnownOne, APInt &KnownOne,
const SelectionDAG &DAG, const SelectionDAG &DAG,
unsigned Depth) const; unsigned Depth) const;
ConstraintType getConstraintType(const std::string &Constraint) const; ConstraintType getConstraintType(const std::string &Constraint) const;
std::pair<unsigned, const TargetRegisterClass*> std::pair<unsigned, const TargetRegisterClass*>
getRegForInlineAsmConstraint(const std::string &Constraint, getRegForInlineAsmConstraint(const std::string &Constraint,

View File

@ -957,7 +957,6 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
maxStoresPerMemset = 16; // For @llvm.memset -> sequence of stores maxStoresPerMemset = 16; // For @llvm.memset -> sequence of stores
maxStoresPerMemcpy = 16; // For @llvm.memcpy -> sequence of stores maxStoresPerMemcpy = 16; // For @llvm.memcpy -> sequence of stores
maxStoresPerMemmove = 3; // For @llvm.memmove -> sequence of stores maxStoresPerMemmove = 3; // For @llvm.memmove -> sequence of stores
allowUnalignedMemoryAccesses = true; // x86 supports it!
setPrefLoopAlignment(16); setPrefLoopAlignment(16);
benefitFromCodePlacementOpt = true; benefitFromCodePlacementOpt = true;
} }

View File

@ -389,10 +389,15 @@ namespace llvm {
/// and store operations as a result of memset, memcpy, and memmove /// and store operations as a result of memset, memcpy, and memmove
/// lowering. It returns EVT::iAny if SelectionDAG should be responsible for /// lowering. It returns EVT::iAny if SelectionDAG should be responsible for
/// determining it. /// determining it.
virtual virtual EVT getOptimalMemOpType(uint64_t Size, unsigned Align,
EVT getOptimalMemOpType(uint64_t Size, unsigned Align, bool isSrcConst, bool isSrcStr,
bool isSrcConst, bool isSrcStr, SelectionDAG &DAG) const;
SelectionDAG &DAG) const;
/// allowsUnalignedMemoryAccesses - Returns true if the target allows
/// unaligned memory accesses. of the specified type.
virtual bool allowsUnalignedMemoryAccesses(EVT VT) const {
return true;
}
/// LowerOperation - Provide custom lowering hooks for some operations. /// LowerOperation - Provide custom lowering hooks for some operations.
/// ///

View File

@ -367,9 +367,10 @@ SDValue XCoreTargetLowering::
LowerLOAD(SDValue Op, SelectionDAG &DAG) LowerLOAD(SDValue Op, SelectionDAG &DAG)
{ {
LoadSDNode *LD = cast<LoadSDNode>(Op); LoadSDNode *LD = cast<LoadSDNode>(Op);
assert(LD->getExtensionType() == ISD::NON_EXTLOAD && "Unexpected extension type"); assert(LD->getExtensionType() == ISD::NON_EXTLOAD &&
"Unexpected extension type");
assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load EVT"); assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load EVT");
if (allowsUnalignedMemoryAccesses()) { if (allowsUnalignedMemoryAccesses(LD->getMemoryVT())) {
return SDValue(); return SDValue();
} }
unsigned ABIAlignment = getTargetData()-> unsigned ABIAlignment = getTargetData()->
@ -465,7 +466,7 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG)
StoreSDNode *ST = cast<StoreSDNode>(Op); StoreSDNode *ST = cast<StoreSDNode>(Op);
assert(!ST->isTruncatingStore() && "Unexpected store type"); assert(!ST->isTruncatingStore() && "Unexpected store type");
assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store EVT"); assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store EVT");
if (allowsUnalignedMemoryAccesses()) { if (allowsUnalignedMemoryAccesses(ST->getMemoryVT())) {
return SDValue(); return SDValue();
} }
unsigned ABIAlignment = getTargetData()-> unsigned ABIAlignment = getTargetData()->
@ -1048,7 +1049,8 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
case ISD::STORE: { case ISD::STORE: {
// Replace unaligned store of unaligned load with memmove. // Replace unaligned store of unaligned load with memmove.
StoreSDNode *ST = cast<StoreSDNode>(N); StoreSDNode *ST = cast<StoreSDNode>(N);
if (!DCI.isBeforeLegalize() || allowsUnalignedMemoryAccesses() || if (!DCI.isBeforeLegalize() ||
allowsUnalignedMemoryAccesses(ST->getMemoryVT()) ||
ST->isVolatile() || ST->isIndexed()) { ST->isVolatile() || ST->isIndexed()) {
break; break;
} }

View File

@ -1,16 +1,31 @@
; RUN: llvm-as < %s | \ ; RUN: llvm-as < %s | llc -march=arm | FileCheck %s -check-prefix=GENERIC
; RUN: llc -march=arm -o %t -f ; RUN: llvm-as < %s | llc -mtriple=armv6-apple-darwin | FileCheck %s -check-prefix=DARWIN_V6
; RUN: grep ldrb %t | count 4 ; RUN: llvm-as < %s | llc -march=arm -mattr=+v7a | FileCheck %s -check-prefix=V7
; RUN: grep strb %t | count 4
; rdar://7113725
%struct.p = type <{ i8, i32 }> define arm_apcscc void @t(i8* nocapture %a, i8* nocapture %b) nounwind {
@t = global %struct.p <{ i8 1, i32 10 }> ; <%struct.p*> [#uses=1]
@u = weak global %struct.p zeroinitializer ; <%struct.p*> [#uses=1]
define i32 @main() {
entry: entry:
%tmp3 = load i32* getelementptr (%struct.p* @t, i32 0, i32 1), align 1 ; <i32> [#uses=2] ; GENERIC: t:
store i32 %tmp3, i32* getelementptr (%struct.p* @u, i32 0, i32 1), align 1 ; GENERIC: ldrb r2
ret i32 %tmp3 ; GENERIC: ldrb r3
; GENERIC: ldrb r12
; GENERIC: ldrb r1
; GENERIC: strb r1
; GENERIC: strb r12
; GENERIC: strb r3
; GENERIC: strb r2
; DARWIN_V6: t:
; DARWIN_V6: ldr r1
; DARWIN_V6: str r1
; V7: t:
; V7: ldr r1
; V7: str r1
%__src1.i = bitcast i8* %b to i32* ; <i32*> [#uses=1]
%__dest2.i = bitcast i8* %a to i32* ; <i32*> [#uses=1]
%tmp.i = load i32* %__src1.i, align 1 ; <i32> [#uses=1]
store i32 %tmp.i, i32* %__dest2.i, align 1
ret void
} }