1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

[SelectionDAG][mips] Fix PR33883

PR33883 shows that calls to intrinsic functions should not have their vector
arguments or returns subject to ABI changes required by the target.

This resolves PR33883.

Thanks to Alex Crichton for reporting the issue!

Reviewers: zoran.jovanovic, atanasyan

Differential Revision: https://reviews.llvm.org/D35765

llvm-svn: 309561
This commit is contained in:
Simon Dardis 2017-07-31 14:06:58 +00:00
parent dca1c68e5c
commit 79d6aa222a
2 changed files with 36 additions and 15 deletions

View File

@ -99,6 +99,27 @@ LimitFPPrecision("limit-float-precision",
// store [4096 x i8] %data, [4096 x i8]* %buffer // store [4096 x i8] %data, [4096 x i8]* %buffer
static const unsigned MaxParallelChains = 64; static const unsigned MaxParallelChains = 64;
// True if the Value passed requires ABI mangling as it is a parameter to a
// function or a return value from a function which is not an intrinsic.
static bool isABIRegCopy(const Value * V) {
const bool IsRetInst = V && isa<ReturnInst>(V);
const bool IsCallInst = V && isa<CallInst>(V);
const bool IsInLineAsm =
IsCallInst && static_cast<const CallInst *>(V)->isInlineAsm();
const bool IsIndirectFunctionCall =
IsCallInst && !IsInLineAsm &&
!static_cast<const CallInst *>(V)->getCalledFunction();
// It is possible that the call instruction is an inline asm statement or an
// indirect function call in which case the return value of
// getCalledFunction() would be nullptr.
const bool IsInstrinsicCall =
IsCallInst && !IsInLineAsm && !IsIndirectFunctionCall &&
static_cast<const CallInst *>(V)->getCalledFunction()->getIntrinsicID() !=
Intrinsic::not_intrinsic;
return IsRetInst || (IsCallInst && (!IsInLineAsm && !IsInstrinsicCall));
}
static SDValue getCopyFromPartsVector(SelectionDAG &DAG, const SDLoc &DL, static SDValue getCopyFromPartsVector(SelectionDAG &DAG, const SDLoc &DL,
const SDValue *Parts, unsigned NumParts, const SDValue *Parts, unsigned NumParts,
MVT PartVT, EVT ValueVT, const Value *V, MVT PartVT, EVT ValueVT, const Value *V,
@ -1024,13 +1045,9 @@ SDValue SelectionDAGBuilder::getCopyFromRegs(const Value *V, Type *Ty) {
if (It != FuncInfo.ValueMap.end()) { if (It != FuncInfo.ValueMap.end()) {
unsigned InReg = It->second; unsigned InReg = It->second;
bool IsABIRegCopy =
V && ((isa<CallInst>(V) &&
!(static_cast<const CallInst *>(V))->isInlineAsm()) ||
isa<ReturnInst>(V));
RegsForValue RFV(*DAG.getContext(), DAG.getTargetLoweringInfo(), RegsForValue RFV(*DAG.getContext(), DAG.getTargetLoweringInfo(),
DAG.getDataLayout(), InReg, Ty, IsABIRegCopy); DAG.getDataLayout(), InReg, Ty, isABIRegCopy(V));
SDValue Chain = DAG.getEntryNode(); SDValue Chain = DAG.getEntryNode();
Result = RFV.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(), Chain, nullptr, Result = RFV.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(), Chain, nullptr,
V); V);
@ -1219,13 +1236,9 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
// If this is an instruction which fast-isel has deferred, select it now. // If this is an instruction which fast-isel has deferred, select it now.
if (const Instruction *Inst = dyn_cast<Instruction>(V)) { if (const Instruction *Inst = dyn_cast<Instruction>(V)) {
unsigned InReg = FuncInfo.InitializeRegForValue(Inst); unsigned InReg = FuncInfo.InitializeRegForValue(Inst);
bool IsABIRegCopy =
V && ((isa<CallInst>(V) &&
!(static_cast<const CallInst *>(V))->isInlineAsm()) ||
isa<ReturnInst>(V));
RegsForValue RFV(*DAG.getContext(), TLI, DAG.getDataLayout(), InReg, RegsForValue RFV(*DAG.getContext(), TLI, DAG.getDataLayout(), InReg,
Inst->getType(), IsABIRegCopy); Inst->getType(), isABIRegCopy(V));
SDValue Chain = DAG.getEntryNode(); SDValue Chain = DAG.getEntryNode();
return RFV.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(), Chain, nullptr, V); return RFV.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(), Chain, nullptr, V);
} }
@ -8275,13 +8288,9 @@ SelectionDAGBuilder::CopyValueToVirtualRegister(const Value *V, unsigned Reg) {
const TargetLowering &TLI = DAG.getTargetLoweringInfo(); const TargetLowering &TLI = DAG.getTargetLoweringInfo();
// If this is an InlineAsm we have to match the registers required, not the // If this is an InlineAsm we have to match the registers required, not the
// notional registers required by the type. // notional registers required by the type.
bool IsABIRegCopy =
V && ((isa<CallInst>(V) &&
!(static_cast<const CallInst *>(V))->isInlineAsm()) ||
isa<ReturnInst>(V));
RegsForValue RFV(V->getContext(), TLI, DAG.getDataLayout(), Reg, RegsForValue RFV(V->getContext(), TLI, DAG.getDataLayout(), Reg,
V->getType(), IsABIRegCopy); V->getType(), isABIRegCopy(V));
SDValue Chain = DAG.getEntryNode(); SDValue Chain = DAG.getEntryNode();
ISD::NodeType ExtendType = (FuncInfo.PreferredExtendType.find(V) == ISD::NodeType ExtendType = (FuncInfo.PreferredExtendType.find(V) ==

View File

@ -0,0 +1,12 @@
; RUN: llc -march=mips -mcpu=mips32 < %s -o /dev/null
; Test that calls to vector intrinsics do not crash SelectionDAGBuilder.
define <4 x float> @_ZN4simd3foo17hebb969c5fb39a194E(<4 x float>) {
start:
%1 = call <4 x float> @llvm.sqrt.v4f32(<4 x float> %0)
ret <4 x float> %1
}
declare <4 x float> @llvm.sqrt.v4f32(<4 x float>)