Skip to content

Commit 26ebe16

Browse files
committed
[SLP]Fix PR88834: check if unsigned arg can be trunced, being used in smax/smin intrinsics.
Need to check that unsigned argument can be safely used in smax/smin intrinsics by checking if at least single sign bit is cleared, otherwise its value may be treated as negative instead of positive.
1 parent 6ab5927 commit 26ebe16

File tree

2 files changed

+15
-5
lines changed

2 files changed

+15
-5
lines changed

llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14639,10 +14639,16 @@ bool BoUpSLP::collectValuesToDemote(
1463914639
assert((ID == Intrinsic::smin || ID == Intrinsic::smax) &&
1464014640
"Expected min/max intrinsics only.");
1464114641
unsigned SignBits = OrigBitWidth - BitWidth;
14642+
APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth - 1);
1464214643
return SignBits <= ComputeNumSignBits(I->getOperand(0), *DL, 0, AC,
1464314644
nullptr, DT) &&
14645+
(!isKnownNonNegative(I->getOperand(0), SimplifyQuery(*DL)) ||
14646+
MaskedValueIsZero(I->getOperand(0), Mask,
14647+
SimplifyQuery(*DL))) &&
1464414648
SignBits <= ComputeNumSignBits(I->getOperand(1), *DL, 0, AC,
14645-
nullptr, DT);
14649+
nullptr, DT) &&
14650+
(!isKnownNonNegative(I->getOperand(1), SimplifyQuery(*DL)) ||
14651+
MaskedValueIsZero(I->getOperand(1), Mask, SimplifyQuery(*DL)));
1464614652
});
1464714653
};
1464814654
if (ID != Intrinsic::abs) {

llvm/test/Transforms/SLPVectorizer/RISCV/smax-unsigned-operand.ll

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ define void @main(ptr noalias %p) {
99
; CHECK-LABEL: define void @main(
1010
; CHECK-SAME: ptr noalias [[P:%.*]]) #[[ATTR0:[0-9]+]] {
1111
; CHECK-NEXT: bb:
12+
; CHECK-NEXT: [[CONV_4:%.*]] = zext i32 0 to i64
13+
; CHECK-NEXT: [[COND_4:%.*]] = tail call i64 @llvm.smax.i64(i64 [[CONV_4]], i64 0)
14+
; CHECK-NEXT: [[CONV5_4:%.*]] = trunc i64 [[COND_4]] to i8
15+
; CHECK-NEXT: store i8 [[CONV5_4]], ptr getelementptr inbounds ([11 x i8], ptr @e, i64 0, i64 4), align 1
1216
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[P]], align 4
13-
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i32> <i32 0, i32 poison>, i32 [[TMP0]], i32 1
14-
; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i32> @llvm.smax.v2i32(<2 x i32> [[TMP1]], <2 x i32> <i32 0, i32 1>)
15-
; CHECK-NEXT: [[TMP3:%.*]] = trunc <2 x i32> [[TMP2]] to <2 x i8>
16-
; CHECK-NEXT: store <2 x i8> [[TMP3]], ptr getelementptr inbounds ([11 x i8], ptr @e, i64 0, i64 4), align 1
17+
; CHECK-NEXT: [[CONV_5:%.*]] = zext i32 [[TMP0]] to i64
18+
; CHECK-NEXT: [[COND_5:%.*]] = tail call i64 @llvm.smax.i64(i64 [[CONV_5]], i64 1)
19+
; CHECK-NEXT: [[CONV5_5:%.*]] = trunc i64 [[COND_5]] to i8
20+
; CHECK-NEXT: store i8 [[CONV5_5]], ptr getelementptr inbounds ([11 x i8], ptr @e, i64 0, i64 5), align 1
1721
; CHECK-NEXT: ret void
1822
;
1923
bb:

0 commit comments

Comments
 (0)