Commit 91c773e1 by Jim Stichnoth

Subzero: Improve the usability of UnimplementedError during lowering.

Provides a variant of the UnimplementedError macro specifically for use in incomplete target instruction lowering. When --skip-unimplemented is specified, the UnimplementedLoweringError macro adds FakeUse and FakeDef instructions in order to maintain consistency in liveness analysis. BUG= none R=kschimpf@google.com Review URL: https://codereview.chromium.org/1591893002 .
parent b819665a
......@@ -459,6 +459,26 @@ void TargetLowering::markRedefinitions() {
}
}
void TargetLowering::addFakeDefUses(const Inst *Instr) {
FOREACH_VAR_IN_INST(Var, *Instr) {
if (auto *Var64 = llvm::dyn_cast<Variable64On32>(Var)) {
Context.insert<InstFakeUse>(Var64->getLo());
Context.insert<InstFakeUse>(Var64->getHi());
} else {
Context.insert<InstFakeUse>(Var);
}
}
Variable *Dest = Instr->getDest();
if (Dest == nullptr)
return;
if (auto *Var64 = llvm::dyn_cast<Variable64On32>(Dest)) {
Context.insert<InstFakeDef>(Var64->getLo());
Context.insert<InstFakeDef>(Var64->getHi());
} else {
Context.insert<InstFakeDef>(Dest);
}
}
void TargetLowering::sortVarsByAlignment(VarList &Dest,
const VarList &Source) const {
Dest = Source;
......
......@@ -45,6 +45,21 @@ namespace Ice {
} \
} while (0)
// UnimplementedLoweringError is similar in style to UnimplementedError. Given
// a TargetLowering object pointer and an Inst pointer, it adds appropriate
// FakeDef and FakeUse instructions to try maintain liveness consistency.
#define UnimplementedLoweringError(Target, Instr) \
do { \
if ((Target)->Ctx->getFlags().getSkipUnimplemented()) { \
(Target)->addFakeDefUses(Instr); \
} else { \
/* Use llvm_unreachable instead of report_fatal_error, which gives \
better stack traces. */ \
llvm_unreachable("Not yet implemented"); \
abort(); \
} \
} while (0)
/// LoweringContext makes it easy to iterate through non-deleted instructions in
/// a node, and insert new (lowered) instructions at the current point. Along
/// with the instruction list container and associated iterators, it holds the
......@@ -373,6 +388,12 @@ protected:
/// before returning.
virtual void postLower() {}
/// When the SkipUnimplemented flag is set, addFakeDefUses() gets invoked by
/// the UnimplementedLoweringError macro to insert fake uses of all the
/// instruction variables and a fake def of the instruction dest, in order to
/// preserve integrity of liveness analysis.
void addFakeDefUses(const Inst *Instr);
/// Find (non-SSA) instructions where the Dest variable appears in some source
/// operand, and set the IsDestRedefined flag. This keeps liveness analysis
/// consistent.
......
......@@ -2787,11 +2787,7 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Instr) {
}
if (isVectorType(DestTy)) {
// Add a fake def to keep liveness consistent in the meantime.
Variable *T = makeReg(DestTy);
Context.insert<InstFakeDef>(T);
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Instr);
return;
}
......@@ -3496,10 +3492,7 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
return;
case InstCast::Sext: {
if (isVectorType(Dest->getType())) {
Variable *T = makeReg(Dest->getType());
Context.insert<InstFakeDef>(T, legalizeToReg(Src0));
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
} else if (Dest->getType() == IceType_i64) {
// t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2
Constant *ShiftAmt = Ctx->getConstantInt32(31);
......@@ -3544,10 +3537,7 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
}
case InstCast::Zext: {
if (isVectorType(Dest->getType())) {
Variable *T = makeReg(Dest->getType());
Context.insert<InstFakeDef>(T, legalizeToReg(Src0));
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
} else if (Dest->getType() == IceType_i64) {
// t1=uxtb src; dst.lo=t1; dst.hi=0
Operand *_0 =
......@@ -3600,10 +3590,7 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
}
case InstCast::Trunc: {
if (isVectorType(Dest->getType())) {
Variable *T = makeReg(Dest->getType());
Context.insert<InstFakeDef>(T, legalizeToReg(Src0));
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
} else {
if (Src0->getType() == IceType_i64)
Src0 = loOperand(Src0);
......@@ -3623,10 +3610,7 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
// fpext: dest.f64 = fptrunc src0.fp32
const bool IsTrunc = CastKind == InstCast::Fptrunc;
if (isVectorType(Dest->getType())) {
Variable *T = makeReg(Dest->getType());
Context.insert<InstFakeDef>(T, legalizeToReg(Src0));
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
break;
}
assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64));
......@@ -3640,10 +3624,7 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
case InstCast::Fptosi:
case InstCast::Fptoui: {
if (isVectorType(Dest->getType())) {
Variable *T = makeReg(Dest->getType());
Context.insert<InstFakeDef>(T, legalizeToReg(Src0));
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
break;
}
......@@ -3679,10 +3660,7 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
case InstCast::Sitofp:
case InstCast::Uitofp: {
if (isVectorType(Dest->getType())) {
Variable *T = makeReg(Dest->getType());
Context.insert<InstFakeDef>(T, legalizeToReg(Src0));
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
break;
}
const bool SourceIsSigned = CastKind == InstCast::Sitofp;
......@@ -3731,13 +3709,13 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
case IceType_void:
llvm::report_fatal_error("Unexpected bitcast.");
case IceType_i1:
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
break;
case IceType_i8:
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
break;
case IceType_i16:
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
break;
case IceType_i32:
case IceType_f32: {
......@@ -3784,11 +3762,7 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
case IceType_v16i8:
case IceType_v4f32:
case IceType_v4i32: {
// avoid liveness errors
Variable *T = makeReg(DestType);
Context.insert<InstFakeDef>(T, legalizeToReg(Src0));
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
break;
}
}
......@@ -3798,12 +3772,7 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
}
void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) {
Variable *Dest = Inst->getDest();
Type DestType = Dest->getType();
Variable *T = makeReg(DestType);
Context.insert<InstFakeDef>(T);
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
}
namespace {
......@@ -3882,10 +3851,7 @@ TargetARM32::CondWhenTrue TargetARM32::lowerFcmpCond(const InstFcmp *Instr) {
void TargetARM32::lowerFcmp(const InstFcmp *Instr) {
Variable *Dest = Instr->getDest();
if (isVectorType(Dest->getType())) {
Variable *T = makeReg(Dest->getType());
Context.insert<InstFakeDef>(T);
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Instr);
return;
}
......@@ -4181,10 +4147,7 @@ void TargetARM32::lowerIcmp(const InstIcmp *Inst) {
Variable *Dest = Inst->getDest();
if (isVectorType(Dest->getType())) {
Variable *T = makeReg(Dest->getType());
Context.insert<InstFakeDef>(T);
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
return;
}
......@@ -4204,8 +4167,7 @@ void TargetARM32::lowerIcmp(const InstIcmp *Inst) {
}
void TargetARM32::lowerInsertElement(const InstInsertElement *Inst) {
(void)Inst;
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
}
namespace {
......@@ -4749,10 +4711,7 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
Type DestTy = Dest->getType();
Variable *T = makeReg(DestTy);
if (isVectorType(DestTy)) {
// Add a fake def to keep liveness consistent in the meantime.
Context.insert<InstFakeDef>(T);
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Instr);
return;
}
_vabs(T, legalizeToReg(Instr->getArg(0)));
......@@ -5343,10 +5302,7 @@ void TargetARM32::lowerSelect(const InstSelect *Inst) {
Operand *Condition = Inst->getCondition();
if (isVectorType(DestTy)) {
Variable *T = makeReg(DestTy);
Context.insert<InstFakeDef>(T);
_mov(Dest, T);
UnimplementedError(Func->getContext()->getFlags());
UnimplementedLoweringError(this, Inst);
return;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment