Skip to content

Commit c5cac48

Browse files
committed
[RISCV] Fix lowering of BUILD_VECTORs as VID sequences
This patch fixes a bug when lowering BUILD_VECTOR via VID sequences. After adding support for fractional steps in D106533, elements with zero steps may be skipped if no step has yet been computed. This allowed certain sequences to slip through the cracks, being identified as VID sequences when in fact they are not. The fix for this is to perform a second loop over the BUILD_VECTOR to validate the entire sequence once the step has been computed. This isn't the most efficient, but on balance the code is more readable and maintainable than doing back-validation during the first loop. Fixes the tests introduced in D123785. Reviewed By: craig.topper Differential Revision: https://reviews.llvm.org/D123786
1 parent 0053794 commit c5cac48

File tree

2 files changed

+44
-35
lines changed

2 files changed

+44
-35
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,49 +1941,57 @@ static Optional<VIDSequence> isSimpleVIDSequence(SDValue Op) {
19411941
// A zero-value value difference means that we're somewhere in the middle
19421942
// of a fractional step, e.g. <0,0,0*,0,1,1,1,1>. Wait until we notice a
19431943
// step change before evaluating the sequence.
1944-
if (ValDiff != 0) {
1945-
int64_t Remainder = ValDiff % IdxDiff;
1946-
// Normalize the step if it's greater than 1.
1947-
if (Remainder != ValDiff) {
1948-
// The difference must cleanly divide the element span.
1949-
if (Remainder != 0)
1950-
return None;
1951-
ValDiff /= IdxDiff;
1952-
IdxDiff = 1;
1953-
}
1954-
1955-
if (!SeqStepNum)
1956-
SeqStepNum = ValDiff;
1957-
else if (ValDiff != SeqStepNum)
1958-
return None;
1944+
if (ValDiff == 0)
1945+
continue;
19591946

1960-
if (!SeqStepDenom)
1961-
SeqStepDenom = IdxDiff;
1962-
else if (IdxDiff != *SeqStepDenom)
1947+
int64_t Remainder = ValDiff % IdxDiff;
1948+
// Normalize the step if it's greater than 1.
1949+
if (Remainder != ValDiff) {
1950+
// The difference must cleanly divide the element span.
1951+
if (Remainder != 0)
19631952
return None;
1953+
ValDiff /= IdxDiff;
1954+
IdxDiff = 1;
19641955
}
1965-
}
19661956

1967-
// Record and/or check any addend.
1968-
if (SeqStepNum && SeqStepDenom) {
1969-
uint64_t ExpectedVal =
1970-
(int64_t)(Idx * (uint64_t)*SeqStepNum) / *SeqStepDenom;
1971-
int64_t Addend = SignExtend64(Val - ExpectedVal, EltSizeInBits);
1972-
if (!SeqAddend)
1973-
SeqAddend = Addend;
1974-
else if (SeqAddend != Addend)
1957+
if (!SeqStepNum)
1958+
SeqStepNum = ValDiff;
1959+
else if (ValDiff != SeqStepNum)
1960+
return None;
1961+
1962+
if (!SeqStepDenom)
1963+
SeqStepDenom = IdxDiff;
1964+
else if (IdxDiff != *SeqStepDenom)
19751965
return None;
19761966
}
19771967

19781968
// Record this non-undef element for later.
19791969
if (!PrevElt || PrevElt->first != Val)
19801970
PrevElt = std::make_pair(Val, Idx);
19811971
}
1982-
// We need to have logged both a step and an addend for this to count as
1983-
// a legal index sequence.
1984-
if (!SeqStepNum || !SeqStepDenom || !SeqAddend)
1972+
1973+
// We need to have logged a step for this to count as a legal index sequence.
1974+
if (!SeqStepNum || !SeqStepDenom)
19851975
return None;
19861976

1977+
// Loop back through the sequence and validate elements we might have skipped
1978+
// while waiting for a valid step. While doing this, log any sequence addend.
1979+
for (unsigned Idx = 0; Idx < NumElts; Idx++) {
1980+
if (Op.getOperand(Idx).isUndef())
1981+
continue;
1982+
uint64_t Val = Op.getConstantOperandVal(Idx) &
1983+
maskTrailingOnes<uint64_t>(EltSizeInBits);
1984+
uint64_t ExpectedVal =
1985+
(int64_t)(Idx * (uint64_t)*SeqStepNum) / *SeqStepDenom;
1986+
int64_t Addend = SignExtend64(Val - ExpectedVal, EltSizeInBits);
1987+
if (!SeqAddend)
1988+
SeqAddend = Addend;
1989+
else if (Addend != SeqAddend)
1990+
return None;
1991+
}
1992+
1993+
assert(SeqAddend && "Must have an addend if we have a step");
1994+
19871995
return VIDSequence{*SeqStepNum, *SeqStepDenom, *SeqAddend};
19881996
}
19891997

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -724,23 +724,24 @@ define <8 x i16> @splat_idx_v8i16(<8 x i16> %v, i64 %idx) {
724724
ret <8 x i16> %splat
725725
}
726726

727-
; FIXME: This is not a vid sequence!
728727
define <4 x i8> @buildvec_not_vid_v4i8_1() {
729728
; CHECK-LABEL: buildvec_not_vid_v4i8_1:
730729
; CHECK: # %bb.0:
730+
; CHECK-NEXT: lui a0, %hi(.LCPI37_0)
731+
; CHECK-NEXT: addi a0, a0, %lo(.LCPI37_0)
731732
; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, mu
732-
; CHECK-NEXT: vid.v v8
733+
; CHECK-NEXT: vle8.v v8, (a0)
733734
; CHECK-NEXT: ret
734735
ret <4 x i8> <i8 0, i8 0, i8 2, i8 3>
735736
}
736737

737-
; FIXME: This is not a vid sequence!
738738
define <4 x i8> @buildvec_not_vid_v4i8_2() {
739739
; CHECK-LABEL: buildvec_not_vid_v4i8_2:
740740
; CHECK: # %bb.0:
741+
; CHECK-NEXT: lui a0, %hi(.LCPI38_0)
742+
; CHECK-NEXT: addi a0, a0, %lo(.LCPI38_0)
741743
; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, mu
742-
; CHECK-NEXT: vid.v v8
743-
; CHECK-NEXT: vrsub.vi v8, v8, 3
744+
; CHECK-NEXT: vle8.v v8, (a0)
744745
; CHECK-NEXT: ret
745746
ret <4 x i8> <i8 3, i8 3, i8 1, i8 0>
746747
}

0 commit comments

Comments
 (0)