Skip to content

Commit d0f72f8

Browse files
authored
[RISCV] Consider truncate semantics in performBUILD_VECTORCombine (#81168)
Fixes #80910. Per the documentation in ISDOpcodes.h, for BUILD_VECTOR "The types of the operands must match the vector element type, except that integer types are allowed to be larger than the element type, in which case the operands are implicitly truncated." This transform was assuming that the scalar operand type matched the result type. This resulted in essentially performing a truncate before a binop, instead of after. As demonstrated by the test case changes, this is often not legal.
1 parent 88e5251 commit d0f72f8

File tree

4 files changed

+399
-179
lines changed

4 files changed

+399
-179
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14956,6 +14956,11 @@ static SDValue performBUILD_VECTORCombine(SDNode *N, SelectionDAG &DAG,
1495614956
if (!TLI.isOperationLegalOrCustom(Opcode, VT) || !TLI.isTypeLegal(VT))
1495714957
return SDValue();
1495814958

14959+
// This BUILD_VECTOR involves an implicit truncation, and sinking
14960+
// truncates through binops is non-trivial.
14961+
if (N->op_begin()->getValueType() != VT.getVectorElementType())
14962+
return SDValue();
14963+
1495914964
SmallVector<SDValue> LHSOps;
1496014965
SmallVector<SDValue> RHSOps;
1496114966
for (SDValue Op : N->ops()) {
@@ -14983,6 +14988,7 @@ static SDValue performBUILD_VECTORCombine(SDNode *N, SelectionDAG &DAG,
1498314988
// have different LHS and RHS types.
1498414989
if (Op.getOperand(0).getValueType() != Op.getOperand(1).getValueType())
1498514990
return SDValue();
14991+
1498614992
RHSOps.push_back(Op.getOperand(1));
1498714993
}
1498814994

llvm/test/CodeGen/RISCV/rvv/fixed-vectors-buildvec-of-binop.ll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,8 @@ define <8 x i32> @add_constant_rhs_8xi32_partial(<8 x i32> %vin, i32 %a, i32 %b,
589589
ret <8 x i32> %v3
590590
}
591591

592-
; FIXME: This is currently showing a miscompile, we effectively
592+
; Here we can not pull the ashr through into the vector domain due to
593+
; the truncate semantics of the build_vector. Doing so would
593594
; truncate before the ashr instead of after it, so if %a or %b
594595
; is e.g. UINT32_MAX+1 we get different result.
595596
define <2 x i32> @build_vec_of_trunc_op(i64 %a, i64 %b) {
@@ -608,10 +609,11 @@ define <2 x i32> @build_vec_of_trunc_op(i64 %a, i64 %b) {
608609
;
609610
; RV64-LABEL: build_vec_of_trunc_op:
610611
; RV64: # %bb.0: # %entry
612+
; RV64-NEXT: srli a0, a0, 1
613+
; RV64-NEXT: srli a1, a1, 1
611614
; RV64-NEXT: vsetivli zero, 2, e32, mf2, ta, ma
612615
; RV64-NEXT: vmv.v.x v8, a0
613616
; RV64-NEXT: vslide1down.vx v8, v8, a1
614-
; RV64-NEXT: vsrl.vi v8, v8, 1
615617
; RV64-NEXT: ret
616618
entry:
617619
%conv11.i = ashr i64 %a, 1

0 commit comments

Comments
 (0)