mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-27 13:40:30 +00:00
Make codegen able to handle values of empty types. This is one way
to fix PR9900. I will keep it open until sable is able to comment on it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131294 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
eea6c95d5d
commit
3fa8283744
@ -273,6 +273,9 @@ public:
|
||||
/// @brief Determine if this type could be losslessly bitcast to Ty
|
||||
bool canLosslesslyBitCastTo(const Type *Ty) const;
|
||||
|
||||
/// isEmptyTy - Return true if this type is empty, that is, it has no
|
||||
/// elements or all its elements are empty.
|
||||
bool isEmptyTy() const;
|
||||
|
||||
/// Here are some useful little methods to query what type derived types are
|
||||
/// Note that all other types can just compare to see if this == Type::xxxTy;
|
||||
|
@ -155,6 +155,10 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf) {
|
||||
const PHINode *PN = dyn_cast<PHINode>(I); ++I) {
|
||||
if (PN->use_empty()) continue;
|
||||
|
||||
// Skip empty types
|
||||
if (PN->getType()->isEmptyTy())
|
||||
continue;
|
||||
|
||||
DebugLoc DL = PN->getDebugLoc();
|
||||
unsigned PHIReg = ValueMap[PN];
|
||||
assert(PHIReg && "PHI node does not have an assigned virtual register!");
|
||||
|
@ -1175,6 +1175,10 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
|
||||
/// created for it, emit nodes to copy the value into the virtual
|
||||
/// registers.
|
||||
void SelectionDAGBuilder::CopyToExportRegsIfNeeded(const Value *V) {
|
||||
// Skip empty types
|
||||
if (V->getType()->isEmptyTy())
|
||||
return;
|
||||
|
||||
DenseMap<const Value *, unsigned>::iterator VMI = FuncInfo.ValueMap.find(V);
|
||||
if (VMI != FuncInfo.ValueMap.end()) {
|
||||
assert(!V->use_empty() && "Unused value assigned virtual registers!");
|
||||
@ -2810,16 +2814,18 @@ void SelectionDAGBuilder::visitInsertValue(const InsertValueInst &I) {
|
||||
SmallVector<SDValue, 4> Values(NumAggValues);
|
||||
|
||||
SDValue Agg = getValue(Op0);
|
||||
SDValue Val = getValue(Op1);
|
||||
unsigned i = 0;
|
||||
// Copy the beginning value(s) from the original aggregate.
|
||||
for (; i != LinearIndex; ++i)
|
||||
Values[i] = IntoUndef ? DAG.getUNDEF(AggValueVTs[i]) :
|
||||
SDValue(Agg.getNode(), Agg.getResNo() + i);
|
||||
// Copy values from the inserted value(s).
|
||||
for (; i != LinearIndex + NumValValues; ++i)
|
||||
Values[i] = FromUndef ? DAG.getUNDEF(AggValueVTs[i]) :
|
||||
SDValue(Val.getNode(), Val.getResNo() + i - LinearIndex);
|
||||
if (NumValValues) {
|
||||
SDValue Val = getValue(Op1);
|
||||
for (; i != LinearIndex + NumValValues; ++i)
|
||||
Values[i] = FromUndef ? DAG.getUNDEF(AggValueVTs[i]) :
|
||||
SDValue(Val.getNode(), Val.getResNo() + i - LinearIndex);
|
||||
}
|
||||
// Copy remaining value(s) from the original aggregate.
|
||||
for (; i != NumAggValues; ++i)
|
||||
Values[i] = IntoUndef ? DAG.getUNDEF(AggValueVTs[i]) :
|
||||
@ -2842,6 +2848,13 @@ void SelectionDAGBuilder::visitExtractValue(const ExtractValueInst &I) {
|
||||
ComputeValueVTs(TLI, ValTy, ValValueVTs);
|
||||
|
||||
unsigned NumValValues = ValValueVTs.size();
|
||||
|
||||
// Ignore a extractvalue that produces an empty object
|
||||
if (!NumValValues) {
|
||||
setValue(&I, DAG.getUNDEF(MVT(MVT::Other)));
|
||||
return;
|
||||
}
|
||||
|
||||
SmallVector<SDValue, 4> Values(NumValValues);
|
||||
|
||||
SDValue Agg = getValue(Op0);
|
||||
@ -4827,8 +4840,14 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee,
|
||||
|
||||
for (ImmutableCallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end();
|
||||
i != e; ++i) {
|
||||
SDValue ArgNode = getValue(*i);
|
||||
Entry.Node = ArgNode; Entry.Ty = (*i)->getType();
|
||||
const Value *V = *i;
|
||||
|
||||
// Skip empty types
|
||||
if (V->getType()->isEmptyTy())
|
||||
continue;
|
||||
|
||||
SDValue ArgNode = getValue(V);
|
||||
Entry.Node = ArgNode; Entry.Ty = V->getType();
|
||||
|
||||
unsigned attrInd = i - CS.arg_begin() + 1;
|
||||
Entry.isSExt = CS.paramHasAttr(attrInd, Attribute::SExt);
|
||||
@ -6498,6 +6517,10 @@ SelectionDAGBuilder::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
|
||||
// Ignore dead phi's.
|
||||
if (PN->use_empty()) continue;
|
||||
|
||||
// Skip empty types
|
||||
if (PN->getType()->isEmptyTy())
|
||||
continue;
|
||||
|
||||
unsigned Reg;
|
||||
const Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB);
|
||||
|
||||
|
@ -197,6 +197,25 @@ bool Type::canLosslesslyBitCastTo(const Type *Ty) const {
|
||||
return false; // Other types have no identity values
|
||||
}
|
||||
|
||||
bool Type::isEmptyTy() const {
|
||||
const ArrayType *ATy = dyn_cast<ArrayType>(this);
|
||||
if (ATy) {
|
||||
unsigned NumElements = ATy->getNumElements();
|
||||
return NumElements == 0 || ATy->getElementType()->isEmptyTy();
|
||||
}
|
||||
|
||||
const StructType *STy = dyn_cast<StructType>(this);
|
||||
if (STy) {
|
||||
unsigned NumElements = STy->getNumElements();
|
||||
for (unsigned i = 0; i < NumElements; ++i)
|
||||
if (!STy->getElementType(i)->isEmptyTy())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned Type::getPrimitiveSizeInBits() const {
|
||||
switch (getTypeID()) {
|
||||
case Type::FloatTyID: return 32;
|
||||
|
81
test/CodeGen/Generic/zero-sized-array.ll
Normal file
81
test/CodeGen/Generic/zero-sized-array.ll
Normal file
@ -0,0 +1,81 @@
|
||||
; RUN: llc < %s
|
||||
; PR9900
|
||||
|
||||
%zero = type [0 x i8]
|
||||
%foobar = type { i32, %zero }
|
||||
|
||||
define void @f(%foobar %arg) {
|
||||
%arg1 = extractvalue %foobar %arg, 0
|
||||
%arg2 = extractvalue %foobar %arg, 1
|
||||
call i32 @f2(%zero %arg2, i32 5, i32 42)
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @f2(%zero %x, i32 %y, i32 %z) {
|
||||
ret i32 %y
|
||||
}
|
||||
|
||||
define void @f3(%zero %x, i32 %y) {
|
||||
call i32 @f2(%zero %x, i32 5, i32 %y)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f4(%zero %z) {
|
||||
insertvalue %foobar undef, %zero %z, 1
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f5(%foobar %x) {
|
||||
allocas:
|
||||
%y = extractvalue %foobar %x, 1
|
||||
br label %b1
|
||||
|
||||
b1:
|
||||
%insert120 = insertvalue %foobar undef, %zero %y, 1
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @f6(%zero %x, %zero %y) {
|
||||
b1:
|
||||
br i1 undef, label %end, label %b2
|
||||
|
||||
b2:
|
||||
br label %end
|
||||
|
||||
end:
|
||||
%z = phi %zero [ %y, %b1 ], [ %x, %b2 ]
|
||||
call void @f4(%zero %z)
|
||||
ret void
|
||||
}
|
||||
|
||||
%zero2 = type {}
|
||||
|
||||
define i32 @g1(%zero2 %x, i32 %y, i32 %z) {
|
||||
ret i32 %y
|
||||
}
|
||||
|
||||
define void @g2(%zero2 %x, i32 %y) {
|
||||
call i32 @g1(%zero2 %x, i32 5, i32 %y)
|
||||
ret void
|
||||
}
|
||||
|
||||
%zero2r = type {%zero2}
|
||||
|
||||
define i32 @h1(%zero2r %x, i32 %y, i32 %z) {
|
||||
ret i32 %y
|
||||
}
|
||||
|
||||
define void @h2(%zero2r %x, i32 %y) {
|
||||
call i32 @h1(%zero2r %x, i32 5, i32 %y)
|
||||
ret void
|
||||
}
|
||||
|
||||
%foobar2 = type { i32, %zero2r }
|
||||
|
||||
define void @h3(%foobar2 %arg) {
|
||||
%arg1 = extractvalue %foobar2 %arg, 0
|
||||
%arg2 = extractvalue %foobar2 %arg, 1
|
||||
%arg21 = extractvalue %zero2r %arg2, 0
|
||||
call void @g2(%zero2 %arg21, i32 5)
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue
Block a user