Commit 7e6aa5a1 by John Porto

Subzero. ARM32. Fixes bugs uncovered by the llvm test suite.

parent a1cdd57e
......@@ -1575,7 +1575,9 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const {
case IceType_v4f32:
assert(CondARM32::isUnconditional(Cond) &&
"Moves on <4 x f32> must be unconditional!");
assert(SrcTy == DestTy && "Mov on different vector types");
// Mov between different Src and Dest types is used for bitcasting vectors.
// We still want to make sure SrcTy is a vector type.
assert(isVectorType(SrcTy) && "Mov between vector and scalar.");
Asm->vorrq(Dest, Src0, Src0);
return;
}
......
......@@ -594,10 +594,13 @@ void TargetARM32::genTargetHelperCallFor(Inst *Instr) {
Variable *Dest = Instr->getDest();
Operand *Src0 = Instr->getSrc(0);
const Type DestTy = Dest->getType();
const Type SrcTy = Src0->getType();
auto *CastInstr = llvm::cast<InstCast>(Instr);
const InstCast::OpKind CastKind = CastInstr->getCastKind();
if (isVectorType(DestTy)) {
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);
......@@ -615,7 +618,7 @@ void TargetARM32::genTargetHelperCallFor(Inst *Instr) {
return;
}
const bool DestIsSigned = CastKind == InstCast::Fptosi;
const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType());
const bool Src0IsF32 = isFloat32Asserting32Or64(SrcTy);
Operand *TargetHelper = Ctx->getConstantExternSym(
Src0IsF32 ? (DestIsSigned ? H_fptosi_f32_i64 : H_fptoui_f32_i64)
: (DestIsSigned ? H_fptosi_f64_i64 : H_fptoui_f64_i64));
......@@ -628,7 +631,7 @@ void TargetARM32::genTargetHelperCallFor(Inst *Instr) {
}
case InstCast::Sitofp:
case InstCast::Uitofp: {
if (Src0->getType() != IceType_i64) {
if (SrcTy != IceType_i64) {
return;
}
const bool SourceIsSigned = CastKind == InstCast::Sitofp;
......@@ -643,6 +646,54 @@ void TargetARM32::genTargetHelperCallFor(Inst *Instr) {
Instr->setDeleted();
return;
}
case InstCast::Bitcast: {
if (DestTy == SrcTy) {
return;
}
Variable *CallDest = Dest;
const char *HelperName = nullptr;
switch (DestTy) {
default:
return;
case IceType_i8:
assert(SrcTy == IceType_v8i1);
HelperName = H_bitcast_8xi1_i8;
CallDest = Func->makeVariable(IceType_i32);
break;
case IceType_i16:
assert(SrcTy == IceType_v16i1);
HelperName = H_bitcast_16xi1_i16;
CallDest = Func->makeVariable(IceType_i32);
break;
case IceType_v8i1: {
assert(SrcTy == IceType_i8);
HelperName = H_bitcast_i8_8xi1;
Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
// Arguments to functions are required to be at least 32 bits wide.
Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0);
Src0 = Src0AsI32;
} break;
case IceType_v16i1: {
assert(SrcTy == IceType_i16);
HelperName = H_bitcast_i16_16xi1;
Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
// Arguments to functions are required to be at least 32 bits wide.
Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0);
Src0 = Src0AsI32;
} break;
}
assert(HelperName != nullptr);
constexpr SizeT MaxSrcs = 1;
InstCall *Call = makeHelperCall(HelperName, CallDest, MaxSrcs);
Call->addArg(Src0);
Context.insert(Call);
// The PNaCl ABI disallows i8/i16 return types, so truncate the helper
// call result to the appropriate type as necessary.
if (CallDest->getType() != Dest->getType())
Context.insert<InstCast>(InstCast::Trunc, Dest, CallDest);
Instr->setDeleted();
return;
}
}
llvm::report_fatal_error("Control flow should never have reached here.");
}
......@@ -4022,10 +4073,14 @@ void TargetARM32::lowerCast(const InstCast *Instr) {
UnimplementedLoweringError(this, Instr);
break;
case IceType_i8:
UnimplementedLoweringError(this, Instr);
assert(Src0->getType() == IceType_v8i1);
llvm::report_fatal_error(
"i8 to v8i1 conversion should have been prelowered.");
break;
case IceType_i16:
UnimplementedLoweringError(this, Instr);
assert(Src0->getType() == IceType_v16i1);
llvm::report_fatal_error(
"i16 to v16i1 conversion should have been prelowered.");
break;
case IceType_i32:
case IceType_f32: {
......@@ -4065,14 +4120,26 @@ void TargetARM32::lowerCast(const InstCast *Instr) {
lowerAssign(InstAssign::create(Func, Dest, T));
break;
}
case IceType_v4i1:
case IceType_v8i1:
assert(Src0->getType() == IceType_i8);
llvm::report_fatal_error(
"v8i1 to i8 conversion should have been prelowered.");
break;
case IceType_v16i1:
assert(Src0->getType() == IceType_i16);
llvm::report_fatal_error(
"v16i1 to i16 conversion should have been prelowered.");
break;
case IceType_v4i1:
case IceType_v8i16:
case IceType_v16i8:
case IceType_v4f32:
case IceType_v4i32: {
UnimplementedLoweringError(this, Instr);
assert(typeWidthInBytes(DestType) == typeWidthInBytes(Src0->getType()));
assert(isVectorType(DestType) == isVectorType(Src0->getType()));
Variable *T = makeReg(DestType);
_mov(T, Src0);
_mov(Dest, T);
break;
}
}
......
......@@ -325,6 +325,9 @@ protected:
CondARM32::Cond Pred = CondARM32::AL) {
constexpr bool SetFlags = true;
Context.insert<InstARM32Add>(Dest, Src0, Src1, Pred, SetFlags);
if (SetFlags) {
Context.insert<InstFakeUse>(Dest);
}
}
void _adc(Variable *Dest, Variable *Src0, Operand *Src1,
CondARM32::Cond Pred = CondARM32::AL) {
......@@ -395,6 +398,9 @@ protected:
CondARM32::Cond Pred = CondARM32::AL) {
constexpr bool SetFlags = true;
Context.insert<InstARM32Lsl>(Dest, Src0, Src1, Pred, SetFlags);
if (SetFlags) {
Context.insert<InstFakeUse>(Dest);
}
}
void _lsr(Variable *Dest, Variable *Src0, Operand *Src1,
CondARM32::Cond Pred = CondARM32::AL) {
......@@ -711,6 +717,9 @@ protected:
CondARM32::Cond Pred = CondARM32::AL) {
constexpr bool SetFlags = true;
Context.insert<InstARM32Orr>(Dest, Src0, Src1, Pred, SetFlags);
if (SetFlags) {
Context.insert<InstFakeUse>(Dest);
}
}
void _push(const VarList &Sources) { Context.insert<InstARM32Push>(Sources); }
void _pop(const VarList &Dests) {
......@@ -734,6 +743,9 @@ protected:
CondARM32::Cond Pred = CondARM32::AL) {
constexpr bool SetFlags = true;
Context.insert<InstARM32Rsc>(Dest, Src0, Src1, Pred, SetFlags);
if (SetFlags) {
Context.insert<InstFakeUse>(Dest);
}
}
void _rsc(Variable *Dest, Variable *Src0, Operand *Src1,
CondARM32::Cond Pred = CondARM32::AL) {
......@@ -743,6 +755,9 @@ protected:
CondARM32::Cond Pred = CondARM32::AL) {
constexpr bool SetFlags = true;
Context.insert<InstARM32Rsb>(Dest, Src0, Src1, Pred, SetFlags);
if (SetFlags) {
Context.insert<InstFakeUse>(Dest);
}
}
void _rsb(Variable *Dest, Variable *Src0, Operand *Src1,
CondARM32::Cond Pred = CondARM32::AL) {
......@@ -756,6 +771,9 @@ protected:
CondARM32::Cond Pred = CondARM32::AL) {
constexpr bool SetFlags = true;
Context.insert<InstARM32Sbc>(Dest, Src0, Src1, Pred, SetFlags);
if (SetFlags) {
Context.insert<InstFakeUse>(Dest);
}
}
void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1,
CondARM32::Cond Pred = CondARM32::AL) {
......@@ -788,6 +806,9 @@ protected:
CondARM32::Cond Pred = CondARM32::AL) {
constexpr bool SetFlags = true;
Context.insert<InstARM32Sub>(Dest, Src0, Src1, Pred, SetFlags);
if (SetFlags) {
Context.insert<InstFakeUse>(Dest);
}
}
void _sxt(Variable *Dest, Variable *Src0,
CondARM32::Cond Pred = CondARM32::AL) {
......
......@@ -1954,3 +1954,29 @@ branch2:
; ARM32-LABEL: phi64Undef
; ARM32: mov {{.*}} #0
; ARM32: mov {{.*}} #0
define internal i32 @addOneToUpperAfterShift(i64 %value) {
%a = add i64 %value, 1
%s = lshr i64 %a, 40
%t = trunc i64 %s to i32
%r = add i32 %t, 1
ret i32 %r
; ARM32-LABEL: addOneToUpperAfterShift
; ARM32: adds
; ARM32: adc
; ARM32: lsr
; ARM32: add
}
define internal i32 @subOneToUpperAfterShift(i64 %value) {
%a = sub i64 %value, 1
%s = lshr i64 %a, 40
%t = trunc i64 %s to i32
%r = sub i32 %t, 1
ret i32 %r
; ARM32-LABEL: subOneToUpperAfterShift
; ARM32: subs
; ARM32: sbc
; ARM32: lsr
; ARM32: sub
}
; This file tests bitcasts of vector type. For most operations, these
; should be lowered to a no-op on -O2.
; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \
; RUN: | FileCheck %s
; RUN: %p2i -i %s --filetype=obj --disassemble --args -Om1 \
; RUN: | FileCheck --check-prefix=OPTM1 %s
; RUN: %p2i -i %s --filetype=obj --disassemble --target=x8632 --args -O2 \
; RUN: | FileCheck --check-prefix=X86-O2 --check-prefix=X86 %s
; RUN: %p2i -i %s --filetype=obj --disassemble --target=x8632 --args -Om1 \
; RUN: | FileCheck --check-prefix=X86 %s
; RUN: %p2i -i %s --filetype=obj --disassemble --target=x8664 --args -O2 \
; RUN: | FileCheck --check-prefix=X86-O2 --check-prefix=X86 %s
; RUN: %p2i -i %s --filetype=obj --disassemble --target=x8664 --args -Om1 \
; RUN: | FileCheck --check-prefix=X86 %s
; RUN: %p2i -i %s --filetype=obj --disassemble --target=arm32 --args -O2 \
; RUN: | FileCheck --check-prefix=ARM32-O2-O2 --check-prefix=ARM32 %s
; RUN: %p2i -i %s --filetype=obj --disassemble --target=arm32 --args -Om1 \
; RUN: | FileCheck --check-prefix=ARM32 %s
define internal <16 x i8> @test_bitcast_v16i8_to_v16i8(<16 x i8> %arg) {
entry:
%res = bitcast <16 x i8> %arg to <16 x i8>
ret <16 x i8> %res
; CHECK-LABEL: test_bitcast_v16i8_to_v16i8
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v16i8_to_v16i8
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v16i8_to_v16i8
; ARM32-O2-NEXT: bx
}
define internal <8 x i16> @test_bitcast_v16i8_to_v8i16(<16 x i8> %arg) {
......@@ -20,8 +33,11 @@ entry:
%res = bitcast <16 x i8> %arg to <8 x i16>
ret <8 x i16> %res
; CHECK-LABEL: test_bitcast_v16i8_to_v8i16
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v16i8_to_v8i16
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v16i8_to_v8i16
; ARM32-O2-NEXT: bx
}
define internal <4 x i32> @test_bitcast_v16i8_to_v4i32(<16 x i8> %arg) {
......@@ -29,8 +45,11 @@ entry:
%res = bitcast <16 x i8> %arg to <4 x i32>
ret <4 x i32> %res
; CHECK-LABEL: test_bitcast_v16i8_to_v4i32
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v16i8_to_v4i32
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v16i8_to_v4i32
; ARM32-O2-NEXT: bx
}
define internal <4 x float> @test_bitcast_v16i8_to_v4f32(<16 x i8> %arg) {
......@@ -38,8 +57,11 @@ entry:
%res = bitcast <16 x i8> %arg to <4 x float>
ret <4 x float> %res
; CHECK-LABEL: test_bitcast_v16i8_to_v4f32
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v16i8_to_v4f32
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v16i8_to_v4f32
; ARM32-O2-NEXT: bx
}
define internal <16 x i8> @test_bitcast_v8i16_to_v16i8(<8 x i16> %arg) {
......@@ -47,8 +69,11 @@ entry:
%res = bitcast <8 x i16> %arg to <16 x i8>
ret <16 x i8> %res
; CHECK-LABEL: test_bitcast_v8i16_to_v16i8
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v8i16_to_v16i8
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v8i16_to_v16i8
; ARM32-O2-NEXT: bx
}
define internal <8 x i16> @test_bitcast_v8i16_to_v8i16(<8 x i16> %arg) {
......@@ -56,8 +81,11 @@ entry:
%res = bitcast <8 x i16> %arg to <8 x i16>
ret <8 x i16> %res
; CHECK-LABEL: test_bitcast_v8i16_to_v8i16
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v8i16_to_v8i16
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v8i16_to_v8i16
; ARM32-O2-NEXT: bx
}
define internal <4 x i32> @test_bitcast_v8i16_to_v4i32(<8 x i16> %arg) {
......@@ -65,8 +93,11 @@ entry:
%res = bitcast <8 x i16> %arg to <4 x i32>
ret <4 x i32> %res
; CHECK-LABEL: test_bitcast_v8i16_to_v4i32
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v8i16_to_v4i32
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v8i16_to_v4i32
; ARM32-O2-NEXT: bx
}
define internal <4 x float> @test_bitcast_v8i16_to_v4f32(<8 x i16> %arg) {
......@@ -74,8 +105,11 @@ entry:
%res = bitcast <8 x i16> %arg to <4 x float>
ret <4 x float> %res
; CHECK-LABEL: test_bitcast_v8i16_to_v4f32
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v8i16_to_v4f32
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v8i16_to_v4f32
; ARM32-O2-NEXT: bx
}
define internal <16 x i8> @test_bitcast_v4i32_to_v16i8(<4 x i32> %arg) {
......@@ -83,8 +117,11 @@ entry:
%res = bitcast <4 x i32> %arg to <16 x i8>
ret <16 x i8> %res
; CHECK-LABEL: test_bitcast_v4i32_to_v16i8
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v4i32_to_v16i8
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v4i32_to_v16i8
; ARM32-O2-NEXT: bx
}
define internal <8 x i16> @test_bitcast_v4i32_to_v8i16(<4 x i32> %arg) {
......@@ -92,8 +129,11 @@ entry:
%res = bitcast <4 x i32> %arg to <8 x i16>
ret <8 x i16> %res
; CHECK-LABEL: test_bitcast_v4i32_to_v8i16
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v4i32_to_v8i16
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v4i32_to_v8i16
; ARM32-O2-NEXT: bx
}
define internal <4 x i32> @test_bitcast_v4i32_to_v4i32(<4 x i32> %arg) {
......@@ -101,8 +141,11 @@ entry:
%res = bitcast <4 x i32> %arg to <4 x i32>
ret <4 x i32> %res
; CHECK-LABEL: test_bitcast_v4i32_to_v4i32
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v4i32_to_v4i32
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v4i32_to_v4i32
; ARM32-O2-NEXT: bx
}
define internal <4 x float> @test_bitcast_v4i32_to_v4f32(<4 x i32> %arg) {
......@@ -110,8 +153,11 @@ entry:
%res = bitcast <4 x i32> %arg to <4 x float>
ret <4 x float> %res
; CHECK-LABEL: test_bitcast_v4i32_to_v4f32
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v4i32_to_v4f32
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v4i32_to_v4f32
; ARM32-O2-NEXT: bx
}
define internal <16 x i8> @test_bitcast_v4f32_to_v16i8(<4 x float> %arg) {
......@@ -119,8 +165,11 @@ entry:
%res = bitcast <4 x float> %arg to <16 x i8>
ret <16 x i8> %res
; CHECK-LABEL: test_bitcast_v4f32_to_v16i8
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v4f32_to_v16i8
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v4f32_to_v16i8
; ARM32-O2-NEXT: bx
}
define internal <8 x i16> @test_bitcast_v4f32_to_v8i16(<4 x float> %arg) {
......@@ -128,8 +177,11 @@ entry:
%res = bitcast <4 x float> %arg to <8 x i16>
ret <8 x i16> %res
; CHECK-LABEL: test_bitcast_v4f32_to_v8i16
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v4f32_to_v8i16
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v4f32_to_v8i16
; ARM32-O2-NEXT: bx
}
define internal <4 x i32> @test_bitcast_v4f32_to_v4i32(<4 x float> %arg) {
......@@ -137,8 +189,11 @@ entry:
%res = bitcast <4 x float> %arg to <4 x i32>
ret <4 x i32> %res
; CHECK-LABEL: test_bitcast_v4f32_to_v4i32
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v4f32_to_v4i32
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v4f32_to_v4i32
; ARM32-O2-NEXT: bx
}
define internal <4 x float> @test_bitcast_v4f32_to_v4f32(<4 x float> %arg) {
......@@ -146,8 +201,11 @@ entry:
%res = bitcast <4 x float> %arg to <4 x float>
ret <4 x float> %res
; CHECK-LABEL: test_bitcast_v4f32_to_v4f32
; CHECK-NEXT: ret
; X86-O2-LABEL: test_bitcast_v4f32_to_v4f32
; X86-O2-NEXT: ret
; ARM32-O2-LABEL: test_bitcast_v4f32_to_v4f32
; ARM32-O2-NEXT: bx
}
define internal i32 @test_bitcast_v8i1_to_i8(<8 x i1> %arg) {
......@@ -156,11 +214,11 @@ entry:
%res.i32 = zext i8 %res to i32
ret i32 %res.i32
; CHECK-LABEL: test_bitcast_v8i1_to_i8
; CHECK: call {{.*}} R_{{.*}} __Sz_bitcast_8xi1_i8
; X86-LABEL: test_bitcast_v8i1_to_i8
; X86: call {{.*}} R_{{.*}} __Sz_bitcast_8xi1_i8
; OPTM1-LABEL: test_bitcast_v8i1_to_i8
; OPMT1: call -4
; ARM32-LABEL: test_bitcast_v8i1_to_i8
; ARM32: bl {{.*}} __Sz_bitcast_8xi1_i8
}
define internal i32 @test_bitcast_v16i1_to_i16(<16 x i1> %arg) {
......@@ -169,11 +227,11 @@ entry:
%res.i32 = zext i16 %res to i32
ret i32 %res.i32
; CHECK-LABEL: test_bitcast_v16i1_to_i16
; CHECK: call {{.*}} R_{{.*}} __Sz_bitcast_16xi1_i16
; X86-LABEL: test_bitcast_v16i1_to_i16
; X86: call {{.*}} __Sz_bitcast_16xi1_i16
; OPTM1-LABEL: test_bitcast_v16i1_to_i16
; OPMT1: call -4
; ARM32-LABEL: test_bitcast_v16i1_to_i16
; ARM32: bl {{.*}} __Sz_bitcast_16xi1_i16
}
define internal <8 x i1> @test_bitcast_i8_to_v8i1(i32 %arg) {
......@@ -182,11 +240,11 @@ entry:
%res = bitcast i8 %arg.trunc to <8 x i1>
ret <8 x i1> %res
; CHECK-LABEL: test_bitcast_i8_to_v8i1
; CHECK: call {{.*}} R_{{.*}} __Sz_bitcast_i8_8xi1
; X86-LABEL: test_bitcast_i8_to_v8i1
; X86: call {{.*}} R_{{.*}} __Sz_bitcast_i8_8xi1
; OPTM1-LABEL: test_bitcast_i8_to_v8i1
; OPTM1: call {{.*}} R_{{.*}} __Sz_bitcast_i8_8xi1
; ARM32-LABEL: test_bitcast_i8_to_v8i1
; ARM32: bl {{.*}} __Sz_bitcast_i8_8xi1
}
define internal <16 x i1> @test_bitcast_i16_to_v16i1(i32 %arg) {
......@@ -195,9 +253,9 @@ entry:
%res = bitcast i16 %arg.trunc to <16 x i1>
ret <16 x i1> %res
; CHECK-LABEL: test_bitcast_i16_to_v16i1
; CHECK: call {{.*}} R_{{.*}} __Sz_bitcast_i16_16xi1
; X86-LABEL: test_bitcast_i16_to_v16i1
; X86: call {{.*}} R_{{.*}} __Sz_bitcast_i16_16xi1
; OPTM1-LABEL: test_bitcast_i16_to_v16i1
; OPTM1: call {{.*}} R_{{.*}} __Sz_bitcast_i16_16xi1
; ARM32-LABEL: test_bitcast_i16_to_v16i1
; ARM32: bl {{.*}} __Sz_bitcast_i16_16xi1
}
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