forked from OSchip/llvm-project
[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
This commit is contained in:
parent
00537946aa
commit
c5cac48549
|
@ -1941,37 +1941,27 @@ static Optional<VIDSequence> isSimpleVIDSequence(SDValue Op) {
|
|||
// A zero-value value difference means that we're somewhere in the middle
|
||||
// of a fractional step, e.g. <0,0,0*,0,1,1,1,1>. Wait until we notice a
|
||||
// step change before evaluating the sequence.
|
||||
if (ValDiff != 0) {
|
||||
int64_t Remainder = ValDiff % IdxDiff;
|
||||
// Normalize the step if it's greater than 1.
|
||||
if (Remainder != ValDiff) {
|
||||
// The difference must cleanly divide the element span.
|
||||
if (Remainder != 0)
|
||||
return None;
|
||||
ValDiff /= IdxDiff;
|
||||
IdxDiff = 1;
|
||||
}
|
||||
if (ValDiff == 0)
|
||||
continue;
|
||||
|
||||
if (!SeqStepNum)
|
||||
SeqStepNum = ValDiff;
|
||||
else if (ValDiff != SeqStepNum)
|
||||
return None;
|
||||
|
||||
if (!SeqStepDenom)
|
||||
SeqStepDenom = IdxDiff;
|
||||
else if (IdxDiff != *SeqStepDenom)
|
||||
int64_t Remainder = ValDiff % IdxDiff;
|
||||
// Normalize the step if it's greater than 1.
|
||||
if (Remainder != ValDiff) {
|
||||
// The difference must cleanly divide the element span.
|
||||
if (Remainder != 0)
|
||||
return None;
|
||||
ValDiff /= IdxDiff;
|
||||
IdxDiff = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Record and/or check any addend.
|
||||
if (SeqStepNum && SeqStepDenom) {
|
||||
uint64_t ExpectedVal =
|
||||
(int64_t)(Idx * (uint64_t)*SeqStepNum) / *SeqStepDenom;
|
||||
int64_t Addend = SignExtend64(Val - ExpectedVal, EltSizeInBits);
|
||||
if (!SeqAddend)
|
||||
SeqAddend = Addend;
|
||||
else if (SeqAddend != Addend)
|
||||
if (!SeqStepNum)
|
||||
SeqStepNum = ValDiff;
|
||||
else if (ValDiff != SeqStepNum)
|
||||
return None;
|
||||
|
||||
if (!SeqStepDenom)
|
||||
SeqStepDenom = IdxDiff;
|
||||
else if (IdxDiff != *SeqStepDenom)
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -1979,11 +1969,29 @@ static Optional<VIDSequence> isSimpleVIDSequence(SDValue Op) {
|
|||
if (!PrevElt || PrevElt->first != Val)
|
||||
PrevElt = std::make_pair(Val, Idx);
|
||||
}
|
||||
// We need to have logged both a step and an addend for this to count as
|
||||
// a legal index sequence.
|
||||
if (!SeqStepNum || !SeqStepDenom || !SeqAddend)
|
||||
|
||||
// We need to have logged a step for this to count as a legal index sequence.
|
||||
if (!SeqStepNum || !SeqStepDenom)
|
||||
return None;
|
||||
|
||||
// Loop back through the sequence and validate elements we might have skipped
|
||||
// while waiting for a valid step. While doing this, log any sequence addend.
|
||||
for (unsigned Idx = 0; Idx < NumElts; Idx++) {
|
||||
if (Op.getOperand(Idx).isUndef())
|
||||
continue;
|
||||
uint64_t Val = Op.getConstantOperandVal(Idx) &
|
||||
maskTrailingOnes<uint64_t>(EltSizeInBits);
|
||||
uint64_t ExpectedVal =
|
||||
(int64_t)(Idx * (uint64_t)*SeqStepNum) / *SeqStepDenom;
|
||||
int64_t Addend = SignExtend64(Val - ExpectedVal, EltSizeInBits);
|
||||
if (!SeqAddend)
|
||||
SeqAddend = Addend;
|
||||
else if (Addend != SeqAddend)
|
||||
return None;
|
||||
}
|
||||
|
||||
assert(SeqAddend && "Must have an addend if we have a step");
|
||||
|
||||
return VIDSequence{*SeqStepNum, *SeqStepDenom, *SeqAddend};
|
||||
}
|
||||
|
||||
|
|
|
@ -724,23 +724,24 @@ define <8 x i16> @splat_idx_v8i16(<8 x i16> %v, i64 %idx) {
|
|||
ret <8 x i16> %splat
|
||||
}
|
||||
|
||||
; FIXME: This is not a vid sequence!
|
||||
define <4 x i8> @buildvec_not_vid_v4i8_1() {
|
||||
; CHECK-LABEL: buildvec_not_vid_v4i8_1:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: lui a0, %hi(.LCPI37_0)
|
||||
; CHECK-NEXT: addi a0, a0, %lo(.LCPI37_0)
|
||||
; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, mu
|
||||
; CHECK-NEXT: vid.v v8
|
||||
; CHECK-NEXT: vle8.v v8, (a0)
|
||||
; CHECK-NEXT: ret
|
||||
ret <4 x i8> <i8 0, i8 0, i8 2, i8 3>
|
||||
}
|
||||
|
||||
; FIXME: This is not a vid sequence!
|
||||
define <4 x i8> @buildvec_not_vid_v4i8_2() {
|
||||
; CHECK-LABEL: buildvec_not_vid_v4i8_2:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: lui a0, %hi(.LCPI38_0)
|
||||
; CHECK-NEXT: addi a0, a0, %lo(.LCPI38_0)
|
||||
; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, mu
|
||||
; CHECK-NEXT: vid.v v8
|
||||
; CHECK-NEXT: vrsub.vi v8, v8, 3
|
||||
; CHECK-NEXT: vle8.v v8, (a0)
|
||||
; CHECK-NEXT: ret
|
||||
ret <4 x i8> <i8 3, i8 3, i8 1, i8 0>
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue