Skip to content

Commit 14db069

Browse files
authored
[InstCombine] Fix a cycle when folding fneg(select) with scalable vector types (#112465)
The two folding operations are causing a cycle for the following case with scalable vector types: define <vscale x 2 x double> @test_fneg_select_abs(<vscale x 2 x i1> %cond, <vscale x 2 x double> %b) { %1 = select <vscale x 2 x i1> %cond, <vscale x 2 x double> zeroinitializer, <vscale x 2 x double> %b %2 = fneg fast <vscale x 2 x double> %1 ret <vscale x 2 x double> %2 } 1) fold fneg: -(Cond ? C : Y) -> Cond ? -C : -Y 2) fold select: (Cond ? -X : -Y) -> -(Cond ? X : Y) 1) results in the following since '<vscale x 2 x double> zeroinitializer' passes the check for the immediate constant: %.neg = fneg fast <vscale x 2 x double> zeroinitializer %b.neg = fneg fast <vscale x 2 x double> %b %1 = select fast <vscale x 2 x i1> %cond, <vscale x 2 x double> %.neg, <vscale x 2 x double> %b.neg and so we end up going back and forth between 1) and 2). Attempt to fold scalable vector constants, so that we end up with a splat instead: define <vscale x 2 x double> @test_fneg_select_abs(<vscale x 2 x i1> %cond, <vscale x 2 x double> %b) { %b.neg = fneg fast <vscale x 2 x double> %b %1 = select fast <vscale x 2 x i1> %cond, <vscale x 2 x double> shufflevector (<vscale x 2 x double> insertelement (<vscale x 2 x double> poison, double -0.000000e+00, i64 0), <vscale x 2 x double> poison, <vscale x 2 x i32> zeroinitializer), <vscale x 2 x double> %b.neg ret <vscale x 2 x double> %1 }
1 parent ac4bd74 commit 14db069

File tree

3 files changed

+49
-18
lines changed

3 files changed

+49
-18
lines changed

llvm/lib/IR/ConstantFold.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -581,26 +581,27 @@ Constant *llvm::ConstantFoldUnaryInstruction(unsigned Opcode, Constant *C) {
581581
case Instruction::FNeg:
582582
return ConstantFP::get(C->getContext(), neg(CV));
583583
}
584-
} else if (auto *VTy = dyn_cast<FixedVectorType>(C->getType())) {
585-
586-
Type *Ty = IntegerType::get(VTy->getContext(), 32);
584+
} else if (auto *VTy = dyn_cast<VectorType>(C->getType())) {
587585
// Fast path for splatted constants.
588586
if (Constant *Splat = C->getSplatValue())
589587
if (Constant *Elt = ConstantFoldUnaryInstruction(Opcode, Splat))
590588
return ConstantVector::getSplat(VTy->getElementCount(), Elt);
591589

592-
// Fold each element and create a vector constant from those constants.
593-
SmallVector<Constant *, 16> Result;
594-
for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) {
595-
Constant *ExtractIdx = ConstantInt::get(Ty, i);
596-
Constant *Elt = ConstantExpr::getExtractElement(C, ExtractIdx);
597-
Constant *Res = ConstantFoldUnaryInstruction(Opcode, Elt);
598-
if (!Res)
599-
return nullptr;
600-
Result.push_back(Res);
601-
}
590+
if (auto *FVTy = dyn_cast<FixedVectorType>(VTy)) {
591+
// Fold each element and create a vector constant from those constants.
592+
Type *Ty = IntegerType::get(FVTy->getContext(), 32);
593+
SmallVector<Constant *, 16> Result;
594+
for (unsigned i = 0, e = FVTy->getNumElements(); i != e; ++i) {
595+
Constant *ExtractIdx = ConstantInt::get(Ty, i);
596+
Constant *Elt = ConstantExpr::getExtractElement(C, ExtractIdx);
597+
Constant *Res = ConstantFoldUnaryInstruction(Opcode, Elt);
598+
if (!Res)
599+
return nullptr;
600+
Result.push_back(Res);
601+
}
602602

603-
return ConstantVector::get(Result);
603+
return ConstantVector::get(Result);
604+
}
604605
}
605606

606607
// We don't know how to fold this.

llvm/test/Transforms/InstCombine/fneg.ll

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,4 +1109,36 @@ define float @test_fneg_select_maxnum(float %x) {
11091109
ret float %neg
11101110
}
11111111

1112+
; Check that there's no infinite loop.
1113+
define <vscale x 2 x double> @test_fneg_select_svec(<vscale x 2 x i1> %cond, <vscale x 2 x double> %b) {
1114+
; CHECK-LABEL: @test_fneg_select_svec(
1115+
; CHECK-NEXT: [[TMP2:%.*]] = fneg fast <vscale x 2 x double> [[TMP1:%.*]]
1116+
; CHECK-NEXT: [[TMP3:%.*]] = select fast <vscale x 2 x i1> [[COND:%.*]], <vscale x 2 x double> shufflevector (<vscale x 2 x double> insertelement (<vscale x 2 x double> poison, double -0.000000e+00, i64 0), <vscale x 2 x double> poison, <vscale x 2 x i32> zeroinitializer), <vscale x 2 x double> [[TMP2]]
1117+
; CHECK-NEXT: ret <vscale x 2 x double> [[TMP3]]
1118+
;
1119+
%1 = select <vscale x 2 x i1> %cond, <vscale x 2 x double> zeroinitializer, <vscale x 2 x double> %b
1120+
%2 = fneg fast <vscale x 2 x double> %1
1121+
ret <vscale x 2 x double> %2
1122+
}
1123+
1124+
define <vscale x 2 x double> @test_fneg_select_svec_2(<vscale x 2 x i1> %cond, <vscale x 2 x double> %a) {
1125+
; CHECK-LABEL: @test_fneg_select_svec_2(
1126+
; CHECK-NEXT: [[A_NEG:%.*]] = fneg fast <vscale x 2 x double> [[A:%.*]]
1127+
; CHECK-NEXT: [[TMP1:%.*]] = select fast <vscale x 2 x i1> [[COND:%.*]], <vscale x 2 x double> [[A_NEG]], <vscale x 2 x double> shufflevector (<vscale x 2 x double> insertelement (<vscale x 2 x double> poison, double -0.000000e+00, i64 0), <vscale x 2 x double> poison, <vscale x 2 x i32> zeroinitializer)
1128+
; CHECK-NEXT: ret <vscale x 2 x double> [[TMP1]]
1129+
;
1130+
%1 = select <vscale x 2 x i1> %cond, <vscale x 2 x double> %a, <vscale x 2 x double> zeroinitializer
1131+
%2 = fneg fast <vscale x 2 x double> %1
1132+
ret <vscale x 2 x double> %2
1133+
}
1134+
1135+
define <vscale x 2 x double> @test_fneg_select_svec_3(<vscale x 2 x i1> %cond, <vscale x 2 x double> %b) {
1136+
; CHECK-LABEL: @test_fneg_select_svec_3(
1137+
; CHECK-NEXT: ret <vscale x 2 x double> shufflevector (<vscale x 2 x double> insertelement (<vscale x 2 x double> poison, double -0.000000e+00, i64 0), <vscale x 2 x double> poison, <vscale x 2 x i32> zeroinitializer)
1138+
;
1139+
%1 = select <vscale x 2 x i1> %cond, <vscale x 2 x double> zeroinitializer, <vscale x 2 x double> zeroinitializer
1140+
%2 = fneg fast <vscale x 2 x double> %1
1141+
ret <vscale x 2 x double> %2
1142+
}
1143+
11121144
!0 = !{}

llvm/test/Transforms/InstSimplify/fp-nan.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,7 @@ define <2 x double> @unary_fneg_nan_2(<2 x double> %x) {
237237
; FIXME: This doesn't behave the same way as the fixed-length vectors above
238238
define <vscale x 1 x double> @unary_fneg_nan_2_scalable_vec_0() {
239239
; CHECK-LABEL: @unary_fneg_nan_2_scalable_vec_0(
240-
; CHECK-NEXT: [[R:%.*]] = fneg <vscale x 1 x double> shufflevector (<vscale x 1 x double> insertelement (<vscale x 1 x double> poison, double 0xFFF1234567890ABC, i64 0), <vscale x 1 x double> poison, <vscale x 1 x i32> zeroinitializer)
241-
; CHECK-NEXT: ret <vscale x 1 x double> [[R]]
240+
; CHECK-NEXT: ret <vscale x 1 x double> shufflevector (<vscale x 1 x double> insertelement (<vscale x 1 x double> poison, double 0x7FF1234567890ABC, i64 0), <vscale x 1 x double> poison, <vscale x 1 x i32> zeroinitializer)
242241
;
243242
%r = fneg <vscale x 1 x double> splat (double 0xFFF1234567890ABC)
244243
ret <vscale x 1 x double> %r
@@ -247,8 +246,7 @@ define <vscale x 1 x double> @unary_fneg_nan_2_scalable_vec_0() {
247246
; FIXME: This doesn't behave the same way as the fixed-length vectors above
248247
define <vscale x 1 x double> @unary_fneg_nan_2_scalable_vec_1() {
249248
; CHECK-LABEL: @unary_fneg_nan_2_scalable_vec_1(
250-
; CHECK-NEXT: [[R:%.*]] = fneg <vscale x 1 x double> shufflevector (<vscale x 1 x double> insertelement (<vscale x 1 x double> poison, double 0x7FF0000000000001, i64 0), <vscale x 1 x double> poison, <vscale x 1 x i32> zeroinitializer)
251-
; CHECK-NEXT: ret <vscale x 1 x double> [[R]]
249+
; CHECK-NEXT: ret <vscale x 1 x double> shufflevector (<vscale x 1 x double> insertelement (<vscale x 1 x double> poison, double 0xFFF0000000000001, i64 0), <vscale x 1 x double> poison, <vscale x 1 x i32> zeroinitializer)
252250
;
253251
%r = fneg <vscale x 1 x double> splat (double 0x7FF0000000000001)
254252
ret <vscale x 1 x double> %r

0 commit comments

Comments
 (0)