Index: src/IceTargetLoweringARM32.cpp |
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp |
index 7a7ed29ab6bd5f62a66a1421681274ad1c78c3f3..b8fa3b684715cff7f043c50973ab870d982c7d75 100644 |
--- a/src/IceTargetLoweringARM32.cpp |
+++ b/src/IceTargetLoweringARM32.cpp |
@@ -599,17 +599,6 @@ void TargetARM32::genTargetHelperCallFor(Inst *Instr) { |
auto *CastInstr = llvm::cast<InstCast>(Instr); |
const InstCast::OpKind CastKind = CastInstr->getCastKind(); |
- if (isVectorType(DestTy) && CastKind != InstCast::Bitcast) { |
- // Bitcasting is done with function calls (e.g., v8i1 -> i8), or regular |
- // vmov (e.g., v4i32 -> v4f32) |
- scalarizeInstruction( |
- Dest, [this, CastKind](Variable *Dest, Variable *Src) { |
- return Context.insert<InstCast>(CastKind, Dest, Src); |
- }, Src0); |
- CastInstr->setDeleted(); |
- return; |
- } |
- |
switch (CastKind) { |
default: |
return; |
@@ -698,6 +687,31 @@ void TargetARM32::genTargetHelperCallFor(Inst *Instr) { |
Instr->setDeleted(); |
return; |
} |
+ case InstCast::Trunc: { |
+ if (DestTy == SrcTy) { |
+ return; |
+ } |
+ if (!isVectorType(SrcTy)) { |
+ return; |
+ } |
+ assert(typeNumElements(DestTy) == typeNumElements(SrcTy)); |
+ assert(typeElementType(DestTy) == IceType_i1); |
+ assert(isVectorIntegerType(SrcTy)); |
+ return; |
+ } |
+ case InstCast::Sext: |
+ case InstCast::Zext: { |
+ if (DestTy == SrcTy) { |
+ return; |
+ } |
+ if (!isVectorType(DestTy)) { |
+ return; |
+ } |
+ assert(typeNumElements(DestTy) == typeNumElements(SrcTy)); |
+ assert(typeElementType(SrcTy) == IceType_i1); |
+ assert(isVectorIntegerType(DestTy)); |
+ return; |
+ } |
} |
llvm::report_fatal_error("Control flow should never have reached here."); |
} |
@@ -3887,15 +3901,35 @@ void configureBitcastTemporary(Variable64On32 *Var) { |
void TargetARM32::lowerCast(const InstCast *Instr) { |
InstCast::OpKind CastKind = Instr->getCastKind(); |
Variable *Dest = Instr->getDest(); |
+ const Type DestTy = Dest->getType(); |
Operand *Src0 = legalizeUndef(Instr->getSrc(0)); |
switch (CastKind) { |
default: |
Func->setError("Cast type not supported"); |
return; |
case InstCast::Sext: { |
- if (isVectorType(Dest->getType())) { |
- UnimplementedLoweringError(this, Instr); |
- } else if (Dest->getType() == IceType_i64) { |
+ if (isVectorType(DestTy)) { |
+ Variable *T0 = makeReg(DestTy); |
+ Variable *T1 = makeReg(DestTy); |
+ ConstantInteger32 *ShAmt = nullptr; |
+ switch (DestTy) { |
+ default: |
+ llvm::report_fatal_error("Unexpected type in vector sext."); |
+ case IceType_v16i8: |
+ ShAmt = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(7)); |
+ break; |
+ case IceType_v8i16: |
+ ShAmt = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(15)); |
+ break; |
+ case IceType_v4i32: |
+ ShAmt = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(31)); |
+ break; |
+ } |
+ auto *Src0R = legalizeToReg(Src0); |
+ _vshl(T0, Src0R, ShAmt); |
+ _vshr(T1, T0, ShAmt)->setSignType(InstARM32::FS_Signed); |
+ _mov(Dest, T1); |
+ } else if (DestTy == IceType_i64) { |
// t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2 |
Constant *ShiftAmt = Ctx->getConstantInt32(31); |
auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
@@ -3925,22 +3959,28 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
} else if (Src0->getType() != IceType_i1) { |
// t1 = sxt src; dst = t1 |
Variable *Src0R = legalizeToReg(Src0); |
- Variable *T = makeReg(Dest->getType()); |
+ Variable *T = makeReg(DestTy); |
_sxt(T, Src0R); |
_mov(Dest, T); |
} else { |
Constant *_0 = Ctx->getConstantZero(IceType_i32); |
- Operand *_m1 = Ctx->getConstantInt(Dest->getType(), -1); |
- Variable *T = makeReg(Dest->getType()); |
+ Operand *_m1 = Ctx->getConstantInt(DestTy, -1); |
+ Variable *T = makeReg(DestTy); |
lowerInt1ForSelect(T, Src0, _m1, _0); |
_mov(Dest, T); |
} |
break; |
} |
case InstCast::Zext: { |
- if (isVectorType(Dest->getType())) { |
- UnimplementedLoweringError(this, Instr); |
- } else if (Dest->getType() == IceType_i64) { |
+ if (isVectorType(DestTy)) { |
+ auto *Mask = makeReg(DestTy); |
+ auto *_1 = Ctx->getConstantInt32(1); |
+ auto *T = makeReg(DestTy); |
+ auto *Src0R = legalizeToReg(Src0); |
+ _mov(Mask, _1); |
+ _vand(T, Src0R, Mask); |
+ _mov(Dest, T); |
+ } else if (DestTy == IceType_i64) { |
// t1=uxtb src; dst.lo=t1; dst.hi=0 |
Operand *_0 = |
legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
@@ -3972,7 +4012,7 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
_mov(T_Hi, _0); |
_mov(DestHi, T_Hi); |
} else if (Src0->getType() == IceType_i1) { |
- Variable *T = makeReg(Dest->getType()); |
+ Variable *T = makeReg(DestTy); |
SafeBoolChain Safe = lowerInt1(T, Src0); |
if (Safe == SBC_No) { |
@@ -3984,23 +4024,26 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
} else { |
// t1 = uxt src; dst = t1 |
Variable *Src0R = legalizeToReg(Src0); |
- Variable *T = makeReg(Dest->getType()); |
+ Variable *T = makeReg(DestTy); |
_uxt(T, Src0R); |
_mov(Dest, T); |
} |
break; |
} |
case InstCast::Trunc: { |
- if (isVectorType(Dest->getType())) { |
- UnimplementedLoweringError(this, Instr); |
+ if (isVectorType(DestTy)) { |
+ auto *T = makeReg(DestTy); |
+ auto *Src0R = legalizeToReg(Src0); |
+ _mov(T, Src0R); |
+ _mov(Dest, T); |
} else { |
if (Src0->getType() == IceType_i64) |
Src0 = loOperand(Src0); |
Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex); |
// t1 = trunc Src0RF; Dest = t1 |
- Variable *T = makeReg(Dest->getType()); |
+ Variable *T = makeReg(DestTy); |
_mov(T, Src0RF); |
- if (Dest->getType() == IceType_i1) |
+ if (DestTy == IceType_i1) |
_and(T, T, Ctx->getConstantInt1(1)); |
_mov(Dest, T); |
} |
@@ -4011,26 +4054,29 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
// fptrunc: dest.f32 = fptrunc src0.fp64 |
// fpext: dest.f64 = fptrunc src0.fp32 |
const bool IsTrunc = CastKind == InstCast::Fptrunc; |
- if (isVectorType(Dest->getType())) { |
- UnimplementedLoweringError(this, Instr); |
- break; |
- } |
- assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64)); |
+ assert(!isVectorType(DestTy)); |
+ assert(DestTy == (IsTrunc ? IceType_f32 : IceType_f64)); |
assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32)); |
Variable *Src0R = legalizeToReg(Src0); |
- Variable *T = makeReg(Dest->getType()); |
+ Variable *T = makeReg(DestTy); |
_vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d); |
_mov(Dest, T); |
break; |
} |
case InstCast::Fptosi: |
case InstCast::Fptoui: { |
- if (isVectorType(Dest->getType())) { |
- UnimplementedLoweringError(this, Instr); |
+ const bool DestIsSigned = CastKind == InstCast::Fptosi; |
+ Variable *Src0R = legalizeToReg(Src0); |
+ |
+ if (isVectorType(DestTy)) { |
+ assert(typeElementType(Src0->getType()) == IceType_f32); |
+ auto *T = makeReg(DestTy); |
+ _vcvt(T, Src0R, |
+ DestIsSigned ? InstARM32Vcvt::Vs2si : InstARM32Vcvt::Vs2ui); |
+ _mov(Dest, T); |
break; |
} |
- const bool DestIsSigned = CastKind == InstCast::Fptosi; |
const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType()); |
if (llvm::isa<Variable64On32>(Dest)) { |
llvm::report_fatal_error("fp-to-i64 should have been pre-lowered."); |
@@ -4043,7 +4089,6 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
// t1.fp = vcvt src0.fp |
// t2.u32 = vmov t1.fp |
// dest.uint = conv t2.u32 @ Truncates the result if needed. |
- Variable *Src0R = legalizeToReg(Src0); |
Variable *T_fp = makeReg(IceType_f32); |
const InstARM32Vcvt::VcvtVariant Conversion = |
Src0IsF32 ? (DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui) |
@@ -4051,8 +4096,8 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
_vcvt(T_fp, Src0R, Conversion); |
Variable *T = makeReg(IceType_i32); |
_mov(T, T_fp); |
- if (Dest->getType() != IceType_i32) { |
- Variable *T_1 = makeReg(Dest->getType()); |
+ if (DestTy != IceType_i32) { |
+ Variable *T_1 = makeReg(DestTy); |
lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T)); |
T = T_1; |
} |
@@ -4061,12 +4106,19 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
} |
case InstCast::Sitofp: |
case InstCast::Uitofp: { |
- if (isVectorType(Dest->getType())) { |
- UnimplementedLoweringError(this, Instr); |
+ const bool SourceIsSigned = CastKind == InstCast::Sitofp; |
+ |
+ if (isVectorType(DestTy)) { |
+ assert(typeElementType(DestTy) == IceType_f32); |
+ auto *T = makeReg(DestTy); |
+ Variable *Src0R = legalizeToReg(Src0); |
+ _vcvt(T, Src0R, |
+ SourceIsSigned ? InstARM32Vcvt::Vsi2s : InstARM32Vcvt::Vui2s); |
+ _mov(Dest, T); |
break; |
} |
- const bool SourceIsSigned = CastKind == InstCast::Sitofp; |
- const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType()); |
+ |
+ const bool DestIsF32 = isFloat32Asserting32Or64(DestTy); |
if (Src0->getType() == IceType_i64) { |
llvm::report_fatal_error("i64-to-fp should have been pre-lowered."); |
} |
@@ -4089,7 +4141,7 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
Variable *Src0R_f32 = makeReg(IceType_f32); |
_mov(Src0R_f32, Src0R); |
Src0R = Src0R_f32; |
- Variable *T = makeReg(Dest->getType()); |
+ Variable *T = makeReg(DestTy); |
const InstARM32Vcvt::VcvtVariant Conversion = |
DestIsF32 |
? (SourceIsSigned ? InstARM32Vcvt::Si2s : InstARM32Vcvt::Ui2s) |
@@ -4100,13 +4152,12 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
} |
case InstCast::Bitcast: { |
Operand *Src0 = Instr->getSrc(0); |
- if (Dest->getType() == Src0->getType()) { |
+ if (DestTy == Src0->getType()) { |
auto *Assign = InstAssign::create(Func, Dest, Src0); |
lowerAssign(Assign); |
return; |
} |
- Type DestType = Dest->getType(); |
- switch (DestType) { |
+ switch (DestTy) { |
case IceType_NUM: |
case IceType_void: |
llvm::report_fatal_error("Unexpected bitcast."); |
@@ -4126,7 +4177,7 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
case IceType_i32: |
case IceType_f32: { |
Variable *Src0R = legalizeToReg(Src0); |
- Variable *T = makeReg(DestType); |
+ Variable *T = makeReg(DestTy); |
_mov(T, Src0R); |
lowerAssign(InstAssign::create(Func, Dest, T)); |
break; |
@@ -4152,7 +4203,7 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
// vmov T2, T0, T1 |
// Dest <- T2 |
assert(Src0->getType() == IceType_i64); |
- Variable *T = makeReg(DestType); |
+ Variable *T = makeReg(DestTy); |
auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); |
Src64->initHiLo(Func); |
configureBitcastTemporary(Src64); |
@@ -4176,9 +4227,9 @@ void TargetARM32::lowerCast(const InstCast *Instr) { |
case IceType_v16i8: |
case IceType_v4f32: |
case IceType_v4i32: { |
- assert(typeWidthInBytes(DestType) == typeWidthInBytes(Src0->getType())); |
- assert(isVectorType(DestType) == isVectorType(Src0->getType())); |
- Variable *T = makeReg(DestType); |
+ assert(typeWidthInBytes(DestTy) == typeWidthInBytes(Src0->getType())); |
+ assert(isVectorType(DestTy) == isVectorType(Src0->getType())); |
+ Variable *T = makeReg(DestTy); |
_mov(T, Src0); |
_mov(Dest, T); |
break; |