Chromium Code Reviews| Index: src/IceTargetLoweringARM32.cpp |
| diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp |
| index 167e37c2dc1e0af621fd215b6902a40f5a759f8f..3bb85d4f501a415bda43c62f8537f7b277fb2193 100644 |
| --- a/src/IceTargetLoweringARM32.cpp |
| +++ b/src/IceTargetLoweringARM32.cpp |
| @@ -34,14 +34,18 @@ namespace Ice { |
| namespace { |
| -void UnimplementedError(const ClFlags &Flags) { |
| - if (!Flags.getSkipUnimplemented()) { |
| - // Use llvm_unreachable instead of report_fatal_error, which gives better |
| - // stack traces. |
| - llvm_unreachable("Not yet implemented"); |
| - abort(); |
| - } |
| -} |
| +// UnimplementedError is defined as a macro so that we can get actual line |
| +// numbers. |
| +#define UnimplementedError(Flags) \ |
| + do { \ |
| + if (!static_cast<const ClFlags &>(Flags).getSkipUnimplemented()) { \ |
| + /* Use llvm_unreachable instead of report_fatal_error, which gives \ |
| + better \ |
| + stack traces. */ \ |
|
ascull
2015/09/10 16:44:09
reflow
John
2015/09/11 12:16:48
Done.
|
| + llvm_unreachable("Not yet implemented"); \ |
| + abort(); \ |
| + } \ |
| + } while (0) |
| // The following table summarizes the logic for lowering the icmp instruction |
| // for i32 and narrower types. Each icmp condition has a clear mapping to an |
| @@ -2075,25 +2079,97 @@ void TargetARM32::lowerCast(const InstCast *Inst) { |
| break; |
| } |
| case InstCast::Fptrunc: |
| - UnimplementedError(Func->getContext()->getFlags()); |
| - break; |
| case InstCast::Fpext: { |
| - UnimplementedError(Func->getContext()->getFlags()); |
| + // fptrunc: dest.f32 = fptrunc src0.fp64 |
| + // fpext: dest.f64 = fptrunc src0.fp32 |
| + const bool IsTrunc = CastKind == InstCast::Fptrunc; |
| + if (isVectorType(Dest->getType())) { |
| + UnimplementedError(Func->getContext()->getFlags()); |
| + break; |
| + } |
| + assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64)); |
| + assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32)); |
| + Variable *Src0R = legalizeToReg(Src0); |
| + Variable *T = makeReg(Dest->getType()); |
| + _vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d); |
| + _mov(Dest, T); |
| break; |
| } |
| case InstCast::Fptosi: |
| - UnimplementedError(Func->getContext()->getFlags()); |
| - // Add a fake def to keep liveness consistent in the meantime. |
| - Context.insert(InstFakeDef::create(Func, Dest)); |
| - break; |
| - case InstCast::Fptoui: |
| - UnimplementedError(Func->getContext()->getFlags()); |
| + case InstCast::Fptoui: { |
| + // fptosi: |
| + // t1.fp = vcvt src0.fp |
| + // t2.i32 = vmov t1.fp |
| + // dest.int = conv t2.i32 @ Truncates the result if needed. |
| + // fptoui: |
| + // t1.fp = vcvt src0.fp |
| + // t2.u32 = vmov t1.fp |
| + // dest.uint = conv t2.u32 @ Truncates the result if needed. |
| + if (isVectorType(Dest->getType())) { |
| + UnimplementedError(Func->getContext()->getFlags()); |
| + break; |
| + } else if (Dest->getType() == IceType_i64) { |
|
Jim Stichnoth
2015/09/10 17:17:10
Make this a separate "if" statement instead of "el
John
2015/09/11 12:16:48
I tend to prefer the looks of
if (Cond1) {
Body
Jim Stichnoth
2015/09/11 13:49:40
I brought it up because LLVM seems to opine pretty
|
| + UnimplementedError(Func->getContext()->getFlags()); |
| + break; |
| + } |
| + const bool DestIsSigned = CastKind == InstCast::Fptosi; |
| + Variable *Src0R = legalizeToReg(Src0); |
| + Variable *T_fp = makeReg(IceType_f32); |
| + if (isFloat32Asserting32Or64(Src0->getType())) { |
| + _vcvt(T_fp, Src0R, |
| + DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui); |
| + } else { |
| + _vcvt(T_fp, Src0R, |
| + DestIsSigned ? InstARM32Vcvt::D2si : InstARM32Vcvt::D2ui); |
| + } |
| + Variable *T = makeReg(IceType_i32); |
| + _vmov(T, T_fp); |
| + if (Dest->getType() != IceType_i32) { |
| + Variable *T_1 = makeReg(Dest->getType()); |
| + lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T)); |
| + T = T_1; |
| + } |
| + _mov(Dest, T); |
| break; |
| + } |
| case InstCast::Sitofp: |
| - UnimplementedError(Func->getContext()->getFlags()); |
| - break; |
| case InstCast::Uitofp: { |
| - UnimplementedError(Func->getContext()->getFlags()); |
| + // sitofp: |
| + // t1.i32 = sext src.int @ sign-extends src0 if needed. |
| + // t2.fp32 = vmov t1.i32 |
| + // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 |
| + // uitofp: |
| + // t1.i32 = zext src.int @ zero-extends src0 if needed. |
| + // t2.fp32 = vmov t1.i32 |
| + // t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64 |
| + if (isVectorType(Dest->getType())) { |
| + UnimplementedError(Func->getContext()->getFlags()); |
| + break; |
| + } else if (Src0->getType() == IceType_i64) { |
| + UnimplementedError(Func->getContext()->getFlags()); |
| + break; |
| + } |
| + const bool SourceIsSigned = CastKind == InstCast::Sitofp; |
| + if (Src0->getType() != IceType_i32) { |
| + Variable *Src0R_32 = makeReg(IceType_i32); |
| + lowerCast(InstCast::create(Func, SourceIsSigned ? InstCast::Sext |
| + : InstCast::Zext, |
| + Src0R_32, Src0)); |
| + Src0 = Src0R_32; |
| + } |
| + Variable *Src0R = legalizeToReg(Src0); |
| + Variable *Src0R_f32 = makeReg(IceType_f32); |
| + _vmov(Src0R_f32, Src0R); |
| + Src0R = Src0R_f32; |
| + Variable *T = makeReg(Dest->getType()); |
| + if (isFloat32Asserting32Or64(Dest->getType())) { |
| + _vcvt(T, Src0R, |
| + SourceIsSigned ? InstARM32Vcvt::Si2s : InstARM32Vcvt::Ui2s); |
| + } else { |
| + _vcvt(T, Src0R, |
| + SourceIsSigned ? InstARM32Vcvt::Si2d : InstARM32Vcvt::Ui2d); |
| + } |
| + _mov(Dest, T); |
| break; |
| } |
| case InstCast::Bitcast: { |