mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-13 15:37:24 +00:00
ARM & AArch64: teach LowerVSETCC that output type size may differ from input.
While various DAG combines try to guarantee that a vector SETCC operation will have the same output size as input, there's nothing intrinsic to either creation or LegalizeTypes that actually guarantees it, so the function needs to be ready to handle a mismatch. Fortunately this is easy enough, just extend or truncate the naturally compared result. I couldn't reproduce the failure in other backends that I know have SIMD, so it's probably only an issue for these two due to shared heritage. Should fix PR21645. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228518 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2c797c6dc4
commit
848d812931
@ -6270,6 +6270,8 @@ static SDValue EmitVectorComparison(SDValue LHS, SDValue RHS,
|
||||
AArch64CC::CondCode CC, bool NoNans, EVT VT,
|
||||
SDLoc dl, SelectionDAG &DAG) {
|
||||
EVT SrcVT = LHS.getValueType();
|
||||
assert(VT.getSizeInBits() == SrcVT.getSizeInBits() &&
|
||||
"function only supposed to emit natural comparisons");
|
||||
|
||||
BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(RHS.getNode());
|
||||
APInt CnstBits(VT.getSizeInBits(), 0);
|
||||
@ -6364,13 +6366,15 @@ SDValue AArch64TargetLowering::LowerVSETCC(SDValue Op,
|
||||
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
|
||||
SDValue LHS = Op.getOperand(0);
|
||||
SDValue RHS = Op.getOperand(1);
|
||||
EVT CmpVT = LHS.getValueType().changeVectorElementTypeToInteger();
|
||||
SDLoc dl(Op);
|
||||
|
||||
if (LHS.getValueType().getVectorElementType().isInteger()) {
|
||||
assert(LHS.getValueType() == RHS.getValueType());
|
||||
AArch64CC::CondCode AArch64CC = changeIntCCToAArch64CC(CC);
|
||||
return EmitVectorComparison(LHS, RHS, AArch64CC, false, Op.getValueType(),
|
||||
dl, DAG);
|
||||
SDValue Cmp =
|
||||
EmitVectorComparison(LHS, RHS, AArch64CC, false, CmpVT, dl, DAG);
|
||||
return DAG.getSExtOrTrunc(Cmp, dl, Op.getValueType());
|
||||
}
|
||||
|
||||
assert(LHS.getValueType().getVectorElementType() == MVT::f32 ||
|
||||
@ -6384,19 +6388,21 @@ SDValue AArch64TargetLowering::LowerVSETCC(SDValue Op,
|
||||
|
||||
bool NoNaNs = getTargetMachine().Options.NoNaNsFPMath;
|
||||
SDValue Cmp =
|
||||
EmitVectorComparison(LHS, RHS, CC1, NoNaNs, Op.getValueType(), dl, DAG);
|
||||
EmitVectorComparison(LHS, RHS, CC1, NoNaNs, CmpVT, dl, DAG);
|
||||
if (!Cmp.getNode())
|
||||
return SDValue();
|
||||
|
||||
if (CC2 != AArch64CC::AL) {
|
||||
SDValue Cmp2 =
|
||||
EmitVectorComparison(LHS, RHS, CC2, NoNaNs, Op.getValueType(), dl, DAG);
|
||||
EmitVectorComparison(LHS, RHS, CC2, NoNaNs, CmpVT, dl, DAG);
|
||||
if (!Cmp2.getNode())
|
||||
return SDValue();
|
||||
|
||||
Cmp = DAG.getNode(ISD::OR, dl, Cmp.getValueType(), Cmp, Cmp2);
|
||||
Cmp = DAG.getNode(ISD::OR, dl, CmpVT, Cmp, Cmp2);
|
||||
}
|
||||
|
||||
Cmp = DAG.getSExtOrTrunc(Cmp, dl, Op.getValueType());
|
||||
|
||||
if (ShouldInvert)
|
||||
return Cmp = DAG.getNOT(dl, Cmp, Cmp.getValueType());
|
||||
|
||||
|
@ -4480,6 +4480,7 @@ static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) {
|
||||
SDValue Op0 = Op.getOperand(0);
|
||||
SDValue Op1 = Op.getOperand(1);
|
||||
SDValue CC = Op.getOperand(2);
|
||||
EVT CmpVT = Op0.getValueType().changeVectorElementTypeToInteger();
|
||||
EVT VT = Op.getValueType();
|
||||
ISD::CondCode SetCCOpcode = cast<CondCodeSDNode>(CC)->get();
|
||||
SDLoc dl(Op);
|
||||
@ -4509,8 +4510,8 @@ static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) {
|
||||
TmpOp0 = Op0;
|
||||
TmpOp1 = Op1;
|
||||
Opc = ISD::OR;
|
||||
Op0 = DAG.getNode(ARMISD::VCGT, dl, VT, TmpOp1, TmpOp0);
|
||||
Op1 = DAG.getNode(ARMISD::VCGT, dl, VT, TmpOp0, TmpOp1);
|
||||
Op0 = DAG.getNode(ARMISD::VCGT, dl, CmpVT, TmpOp1, TmpOp0);
|
||||
Op1 = DAG.getNode(ARMISD::VCGT, dl, CmpVT, TmpOp0, TmpOp1);
|
||||
break;
|
||||
case ISD::SETUO: Invert = true; // Fallthrough
|
||||
case ISD::SETO:
|
||||
@ -4518,8 +4519,8 @@ static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) {
|
||||
TmpOp0 = Op0;
|
||||
TmpOp1 = Op1;
|
||||
Opc = ISD::OR;
|
||||
Op0 = DAG.getNode(ARMISD::VCGT, dl, VT, TmpOp1, TmpOp0);
|
||||
Op1 = DAG.getNode(ARMISD::VCGE, dl, VT, TmpOp0, TmpOp1);
|
||||
Op0 = DAG.getNode(ARMISD::VCGT, dl, CmpVT, TmpOp1, TmpOp0);
|
||||
Op1 = DAG.getNode(ARMISD::VCGE, dl, CmpVT, TmpOp0, TmpOp1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -4553,8 +4554,8 @@ static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) {
|
||||
|
||||
if (AndOp.getNode() && AndOp.getOpcode() == ISD::AND) {
|
||||
Opc = ARMISD::VTST;
|
||||
Op0 = DAG.getNode(ISD::BITCAST, dl, VT, AndOp.getOperand(0));
|
||||
Op1 = DAG.getNode(ISD::BITCAST, dl, VT, AndOp.getOperand(1));
|
||||
Op0 = DAG.getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(0));
|
||||
Op1 = DAG.getNode(ISD::BITCAST, dl, CmpVT, AndOp.getOperand(1));
|
||||
Invert = !Invert;
|
||||
}
|
||||
}
|
||||
@ -4580,22 +4581,24 @@ static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) {
|
||||
if (SingleOp.getNode()) {
|
||||
switch (Opc) {
|
||||
case ARMISD::VCEQ:
|
||||
Result = DAG.getNode(ARMISD::VCEQZ, dl, VT, SingleOp); break;
|
||||
Result = DAG.getNode(ARMISD::VCEQZ, dl, CmpVT, SingleOp); break;
|
||||
case ARMISD::VCGE:
|
||||
Result = DAG.getNode(ARMISD::VCGEZ, dl, VT, SingleOp); break;
|
||||
Result = DAG.getNode(ARMISD::VCGEZ, dl, CmpVT, SingleOp); break;
|
||||
case ARMISD::VCLEZ:
|
||||
Result = DAG.getNode(ARMISD::VCLEZ, dl, VT, SingleOp); break;
|
||||
Result = DAG.getNode(ARMISD::VCLEZ, dl, CmpVT, SingleOp); break;
|
||||
case ARMISD::VCGT:
|
||||
Result = DAG.getNode(ARMISD::VCGTZ, dl, VT, SingleOp); break;
|
||||
Result = DAG.getNode(ARMISD::VCGTZ, dl, CmpVT, SingleOp); break;
|
||||
case ARMISD::VCLTZ:
|
||||
Result = DAG.getNode(ARMISD::VCLTZ, dl, VT, SingleOp); break;
|
||||
Result = DAG.getNode(ARMISD::VCLTZ, dl, CmpVT, SingleOp); break;
|
||||
default:
|
||||
Result = DAG.getNode(Opc, dl, VT, Op0, Op1);
|
||||
Result = DAG.getNode(Opc, dl, CmpVT, Op0, Op1);
|
||||
}
|
||||
} else {
|
||||
Result = DAG.getNode(Opc, dl, VT, Op0, Op1);
|
||||
Result = DAG.getNode(Opc, dl, CmpVT, Op0, Op1);
|
||||
}
|
||||
|
||||
Result = DAG.getSExtOrTrunc(Result, dl, VT);
|
||||
|
||||
if (Invert)
|
||||
Result = DAG.getNOT(dl, Result, VT);
|
||||
|
||||
|
11
test/CodeGen/AArch64/setcc-type-mismatch.ll
Normal file
11
test/CodeGen/AArch64/setcc-type-mismatch.ll
Normal file
@ -0,0 +1,11 @@
|
||||
; RUN: llc -mtriple=aarch64-linux-gnu %s -o - | FileCheck %s
|
||||
|
||||
define void @test_mismatched_setcc(<4 x i22> %l, <4 x i22> %r, <4 x i1>* %addr) {
|
||||
; CHECK-LABEL: test_mismatched_setcc:
|
||||
; CHECK: cmeq [[CMP128:v[0-9]+]].4s, {{v[0-9]+}}.4s, {{v[0-9]+}}.4s
|
||||
; CHECK: xtn {{v[0-9]+}}.4h, [[CMP128]].4s
|
||||
|
||||
%tst = icmp eq <4 x i22> %l, %r
|
||||
store <4 x i1> %tst, <4 x i1>* %addr
|
||||
ret void
|
||||
}
|
11
test/CodeGen/ARM/setcc-type-mismatch.ll
Normal file
11
test/CodeGen/ARM/setcc-type-mismatch.ll
Normal file
@ -0,0 +1,11 @@
|
||||
; RUN: llc -mtriple=armv7-linux-gnueabihf %s -o - | FileCheck %s
|
||||
|
||||
define void @test_mismatched_setcc(<4 x i22> %l, <4 x i22> %r, <4 x i1>* %addr) {
|
||||
; CHECK-LABEL: test_mismatched_setcc:
|
||||
; CHECK: vceq.i32 [[CMP128:q[0-9]+]], {{q[0-9]+}}, {{q[0-9]+}}
|
||||
; CHECK: vmovn.i32 {{d[0-9]+}}, [[CMP128]]
|
||||
|
||||
%tst = icmp eq <4 x i22> %l, %r
|
||||
store <4 x i1> %tst, <4 x i1>* %addr
|
||||
ret void
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user