diff --git a/lib/Target/AArch64/AArch64FastISel.cpp b/lib/Target/AArch64/AArch64FastISel.cpp index 647bb57deae..8d7bddbea95 100644 --- a/lib/Target/AArch64/AArch64FastISel.cpp +++ b/lib/Target/AArch64/AArch64FastISel.cpp @@ -114,6 +114,7 @@ private: bool SelectIntExt(const Instruction *I); bool SelectMul(const Instruction *I); bool SelectShift(const Instruction *I, bool IsLeftShift, bool IsArithmetic); + bool SelectBitCast(const Instruction *I); // Utility helper routines. bool isTypeLegal(Type *Ty, MVT &VT); @@ -2411,6 +2412,40 @@ bool AArch64FastISel::SelectShift(const Instruction *I, bool IsLeftShift, return true; } +bool AArch64FastISel::SelectBitCast(const Instruction *I) { + MVT RetVT, SrcVT; + + if (!isTypeLegal(I->getOperand(0)->getType(), SrcVT)) + return false; + if (!isTypeLegal(I->getType(), RetVT)) + return false; + + unsigned Opc; + if (RetVT == MVT::f32 && SrcVT == MVT::i32) + Opc = AArch64::FMOVWSr; + else if (RetVT == MVT::f64 && SrcVT == MVT::i64) + Opc = AArch64::FMOVXDr; + else if (RetVT == MVT::i32 && SrcVT == MVT::f32) + Opc = AArch64::FMOVSWr; + else if (RetVT == MVT::i64 && SrcVT == MVT::f64) + Opc = AArch64::FMOVDXr; + else + return false; + + unsigned Op0Reg = getRegForValue(I->getOperand(0)); + if (!Op0Reg) + return false; + bool Op0IsKill = hasTrivialKill(I->getOperand(0)); + unsigned ResultReg = FastEmitInst_r(Opc, TLI.getRegClassFor(RetVT), + Op0Reg, Op0IsKill); + + if (!ResultReg) + return false; + + UpdateValueMap(I, ResultReg); + return true; +} + bool AArch64FastISel::TargetSelectInstruction(const Instruction *I) { switch (I->getOpcode()) { default: @@ -2462,6 +2497,8 @@ bool AArch64FastISel::TargetSelectInstruction(const Instruction *I) { return SelectShift(I, /*IsLeftShift=*/false, /*IsArithmetic=*/false); case Instruction::AShr: return SelectShift(I, /*IsLeftShift=*/false, /*IsArithmetic=*/true); + case Instruction::BitCast: + return SelectBitCast(I); } return false; // Silence warnings. diff --git a/test/CodeGen/AArch64/arm64-fast-isel-conversion.ll b/test/CodeGen/AArch64/arm64-fast-isel-conversion.ll index c5417de0ae9..ab46bb6b582 100644 --- a/test/CodeGen/AArch64/arm64-fast-isel-conversion.ll +++ b/test/CodeGen/AArch64/arm64-fast-isel-conversion.ll @@ -440,3 +440,24 @@ define zeroext i64 @zext_i16_i64(i16 zeroext %in) { %big = zext i16 %in to i64 ret i64 %big } + +define float @bitcast_i32_to_float(i32 %a) { + %1 = bitcast i32 %a to float + ret float %1 +} + +define double @bitcast_i64_to_double(i64 %a) { + %1 = bitcast i64 %a to double + ret double %1 +} + +define i32 @bitcast_float_to_i32(float %a) { + %1 = bitcast float %a to i32 + ret i32 %1 +} + +define i64 @bitcast_double_to_i64(double %a) { + %1 = bitcast double %a to i64 + ret i64 %1 +} +