Skip to content

Commit afb584a

Browse files
authored
[SelectionDAG] Ensure that we don't create UCMP/SCMP nodes with operands being scalars and result being a 1-element vector during scalarization (#98687)
This patch fixes a problem that existed before where in some situations a `UCMP`/`SCMP` node which operated on 1-element vectors had a legal result type (i.e. `v1i64` on AArch64), but illegal operands (i.e. `v1i65`). This meant that operand scalarization was performed on the node and the operands were changed to a legal scalar type, but the result wasn't. This then led to `UCMP`/`SCMP` nodes with different vector-ness of operands and result appearing in the SDAG. This patch addresses this issue by fully scalarizing the `UCMP`/`SCMP` node and then turning its result back into a 1-element vector using a `SCALAR_TO_VECTOR` node. It also adds several assertions to `SelectionDAG::getNode()` to avoid this or a similar issue arising in the future. I wasn't sure if these two changes are unrelated enough to warrant two small separate PRs, but I'm happy to split this PR into two if that's deemed more appropriate.
1 parent bee2403 commit afb584a

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,10 @@ SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE_SEQ(SDNode *N) {
10351035
SDValue DAGTypeLegalizer::ScalarizeVecOp_CMP(SDNode *N) {
10361036
SDValue LHS = GetScalarizedVector(N->getOperand(0));
10371037
SDValue RHS = GetScalarizedVector(N->getOperand(1));
1038-
return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), LHS, RHS);
1038+
1039+
EVT ResVT = N->getValueType(0).getVectorElementType();
1040+
SDValue Cmp = DAG.getNode(N->getOpcode(), SDLoc(N), ResVT, LHS, RHS);
1041+
return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Cmp);
10391042
}
10401043

10411044
//===----------------------------------------------------------------------===//

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6989,6 +6989,17 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
69896989
return getNode(ISD::AND, DL, VT, N1, getNOT(DL, N2, VT));
69906990
}
69916991
break;
6992+
case ISD::SCMP:
6993+
case ISD::UCMP:
6994+
assert(N1.getValueType() == N2.getValueType() &&
6995+
"Types of operands of UCMP/SCMP must match");
6996+
assert(N1.getValueType().isVector() == VT.isVector() &&
6997+
"Operands and return type of must both be scalars or vectors");
6998+
if (VT.isVector())
6999+
assert(VT.getVectorElementCount() ==
7000+
N1.getValueType().getVectorElementCount() &&
7001+
"Result and operands must have the same number of elements");
7002+
break;
69927003
case ISD::AVGFLOORS:
69937004
case ISD::AVGFLOORU:
69947005
case ISD::AVGCEILS:

llvm/test/CodeGen/AArch64/ucmp.ll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,20 @@ define i64 @ucmp.64.64(i64 %x, i64 %y) nounwind {
9393
%1 = call i64 @llvm.ucmp(i64 %x, i64 %y)
9494
ret i64 %1
9595
}
96+
97+
define <1 x i64> @ucmp.1.64.65(<1 x i65> %x, <1 x i65> %y) {
98+
; CHECK-LABEL: ucmp.1.64.65:
99+
; CHECK: // %bb.0:
100+
; CHECK-NEXT: and x8, x1, #0x1
101+
; CHECK-NEXT: and x9, x3, #0x1
102+
; CHECK-NEXT: cmp x2, x0
103+
; CHECK-NEXT: sbcs xzr, x9, x8
104+
; CHECK-NEXT: cset x10, lo
105+
; CHECK-NEXT: cmp x0, x2
106+
; CHECK-NEXT: sbcs xzr, x8, x9
107+
; CHECK-NEXT: csinv x8, x10, xzr, hs
108+
; CHECK-NEXT: fmov d0, x8
109+
; CHECK-NEXT: ret
110+
%1 = call <1 x i64> @llvm.ucmp(<1 x i65> %x, <1 x i65> %y)
111+
ret <1 x i64> %1
112+
}

0 commit comments

Comments
 (0)