mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[PowerPC] Implement PPCTargetLowering::getTgtMemIntrinsic
This implements PPCTargetLowering::getTgtMemIntrinsic for Altivec load/store intrinsics. As with the construction of the MachineMemOperands for the intrinsic calls used for unaligned load/store lowering, the only slight complication is that we need to represent a larger memory range than the loaded/stored value-type size (because the address is rounded down to an aligned address, and we need to conservatively represent the entire possible range of the actual access). This required adding an extra size field to TargetLowering::IntrinsicInfo, and this was done in a way that required no modifications to other targets (the size defaults to the store size of the provided memory data type). This fixes test/CodeGen/PowerPC/unal-altivec-wint.ll (so it can be un-XFAILed). llvm-svn: 215512
This commit is contained in:
parent
ac8c24afbf
commit
97fb1d4d91
@ -802,7 +802,8 @@ public:
|
||||
ArrayRef<SDValue> Ops,
|
||||
EVT MemVT, MachinePointerInfo PtrInfo,
|
||||
unsigned Align = 0, bool Vol = false,
|
||||
bool ReadMem = true, bool WriteMem = true);
|
||||
bool ReadMem = true, bool WriteMem = true,
|
||||
unsigned Size = 0);
|
||||
|
||||
SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList,
|
||||
ArrayRef<SDValue> Ops,
|
||||
|
@ -431,10 +431,15 @@ public:
|
||||
EVT memVT; // memory VT
|
||||
const Value* ptrVal; // value representing memory location
|
||||
int offset; // offset off of ptrVal
|
||||
unsigned size; // the size of the memory location
|
||||
// (taken from memVT if zero)
|
||||
unsigned align; // alignment
|
||||
bool vol; // is volatile?
|
||||
bool readMem; // reads memory?
|
||||
bool writeMem; // writes memory?
|
||||
|
||||
IntrinsicInfo() : opc(0), ptrVal(nullptr), offset(0), size(0), align(1),
|
||||
vol(false), readMem(false), writeMem(false) {}
|
||||
};
|
||||
|
||||
/// Given an intrinsic, checks if on the target the intrinsic will need to map
|
||||
|
@ -4567,7 +4567,7 @@ SelectionDAG::getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList,
|
||||
ArrayRef<SDValue> Ops,
|
||||
EVT MemVT, MachinePointerInfo PtrInfo,
|
||||
unsigned Align, bool Vol,
|
||||
bool ReadMem, bool WriteMem) {
|
||||
bool ReadMem, bool WriteMem, unsigned Size) {
|
||||
if (Align == 0) // Ensure that codegen never sees alignment 0
|
||||
Align = getEVTAlignment(MemVT);
|
||||
|
||||
@ -4579,8 +4579,10 @@ SelectionDAG::getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList,
|
||||
Flags |= MachineMemOperand::MOLoad;
|
||||
if (Vol)
|
||||
Flags |= MachineMemOperand::MOVolatile;
|
||||
if (!Size)
|
||||
Size = MemVT.getStoreSize();
|
||||
MachineMemOperand *MMO =
|
||||
MF.getMachineMemOperand(PtrInfo, Flags, MemVT.getStoreSize(), Align);
|
||||
MF.getMachineMemOperand(PtrInfo, Flags, Size, Align);
|
||||
|
||||
return getMemIntrinsicNode(Opcode, dl, VTList, Ops, MemVT, MMO);
|
||||
}
|
||||
|
@ -3868,7 +3868,7 @@ void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I,
|
||||
VTs, Ops, Info.memVT,
|
||||
MachinePointerInfo(Info.ptrVal, Info.offset),
|
||||
Info.align, Info.vol,
|
||||
Info.readMem, Info.writeMem);
|
||||
Info.readMem, Info.writeMem, Info.size);
|
||||
} else if (!HasChain) {
|
||||
Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, getCurSDLoc(), VTs, Ops);
|
||||
} else if (!I.getType()->isVoidTy()) {
|
||||
|
@ -9206,6 +9206,82 @@ PPCTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PPCTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
|
||||
const CallInst &I,
|
||||
unsigned Intrinsic) const {
|
||||
|
||||
switch (Intrinsic) {
|
||||
case Intrinsic::ppc_altivec_lvx:
|
||||
case Intrinsic::ppc_altivec_lvxl:
|
||||
case Intrinsic::ppc_altivec_lvebx:
|
||||
case Intrinsic::ppc_altivec_lvehx:
|
||||
case Intrinsic::ppc_altivec_lvewx: {
|
||||
EVT VT;
|
||||
switch (Intrinsic) {
|
||||
case Intrinsic::ppc_altivec_lvebx:
|
||||
VT = MVT::i8;
|
||||
break;
|
||||
case Intrinsic::ppc_altivec_lvehx:
|
||||
VT = MVT::i16;
|
||||
break;
|
||||
case Intrinsic::ppc_altivec_lvewx:
|
||||
VT = MVT::i32;
|
||||
break;
|
||||
default:
|
||||
VT = MVT::v4i32;
|
||||
break;
|
||||
}
|
||||
|
||||
Info.opc = ISD::INTRINSIC_W_CHAIN;
|
||||
Info.memVT = VT;
|
||||
Info.ptrVal = I.getArgOperand(0);
|
||||
Info.offset = -VT.getStoreSize()+1;
|
||||
Info.size = 2*VT.getStoreSize()-1;
|
||||
Info.align = 1;
|
||||
Info.vol = false;
|
||||
Info.readMem = true;
|
||||
Info.writeMem = false;
|
||||
return true;
|
||||
}
|
||||
case Intrinsic::ppc_altivec_stvx:
|
||||
case Intrinsic::ppc_altivec_stvxl:
|
||||
case Intrinsic::ppc_altivec_stvebx:
|
||||
case Intrinsic::ppc_altivec_stvehx:
|
||||
case Intrinsic::ppc_altivec_stvewx: {
|
||||
EVT VT;
|
||||
switch (Intrinsic) {
|
||||
case Intrinsic::ppc_altivec_stvebx:
|
||||
VT = MVT::i8;
|
||||
break;
|
||||
case Intrinsic::ppc_altivec_stvehx:
|
||||
VT = MVT::i16;
|
||||
break;
|
||||
case Intrinsic::ppc_altivec_stvewx:
|
||||
VT = MVT::i32;
|
||||
break;
|
||||
default:
|
||||
VT = MVT::v4i32;
|
||||
break;
|
||||
}
|
||||
|
||||
Info.opc = ISD::INTRINSIC_VOID;
|
||||
Info.memVT = VT;
|
||||
Info.ptrVal = I.getArgOperand(1);
|
||||
Info.offset = -VT.getStoreSize()+1;
|
||||
Info.size = 2*VT.getStoreSize()-1;
|
||||
Info.align = 1;
|
||||
Info.vol = false;
|
||||
Info.readMem = false;
|
||||
Info.writeMem = true;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getOptimalMemOpType - Returns the target specific optimal type for load
|
||||
/// and store operations as a result of memset, memcpy, and memmove
|
||||
/// lowering. If DstAlign is zero that means it's safe to destination
|
||||
|
@ -477,6 +477,10 @@ namespace llvm {
|
||||
|
||||
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
|
||||
|
||||
bool getTgtMemIntrinsic(IntrinsicInfo &Info,
|
||||
const CallInst &I,
|
||||
unsigned Intrinsic) const override;
|
||||
|
||||
/// getOptimalMemOpType - Returns the target specific optimal type for load
|
||||
/// and store operations as a result of memset, memcpy, and memmove
|
||||
/// lowering. If DstAlign is zero that means it's safe to destination
|
||||
|
@ -1,7 +1,6 @@
|
||||
; RUN: llc -mcpu=pwr7 < %s | FileCheck %s
|
||||
target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64"
|
||||
target triple = "powerpc64-unknown-linux-gnu"
|
||||
; XFAIL: *
|
||||
|
||||
declare <4 x i32> @llvm.ppc.altivec.lvx(i8*) #1
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user