Skip to content

Commit 9f6e9cf

Browse files
committed
[ConstantFolding] Fold undef for integer intrinsics
This fixes https://bugs.llvm.org/show_bug.cgi?id=40110. This implements handling of undef operands for integer intrinsics in ConstantFolding, in particular for the bitcounting intrinsics (ctpop, cttz, ctlz), the with.overflow intrinsics, the saturating math intrinsics and the funnel shift intrinsics. The undef behavior follows what InstSimplify does for the general cas e of non-constant operands. For the bitcount intrinsics (where InstSimplify doesn't do undef handling -- there cannot be a combination of an undef + non-constant operand) I'm using a 0 result if the intrinsic is defined for zero and undef otherwise. Differential Revision: https://reviews.llvm.org/D55950 llvm-svn: 350971
1 parent c3399db commit 9f6e9cf

File tree

6 files changed

+174
-594
lines changed

6 files changed

+174
-594
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 114 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,18 @@ static bool isManifestConstant(const Constant *c) {
16291629
return false;
16301630
}
16311631

1632+
static bool getConstIntOrUndef(Value *Op, const APInt *&C) {
1633+
if (auto *CI = dyn_cast<ConstantInt>(Op)) {
1634+
C = &CI->getValue();
1635+
return true;
1636+
}
1637+
if (isa<UndefValue>(Op)) {
1638+
C = nullptr;
1639+
return true;
1640+
}
1641+
return false;
1642+
}
1643+
16321644
Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
16331645
ArrayRef<Constant *> Operands,
16341646
const TargetLibraryInfo *TLI,
@@ -1643,8 +1655,10 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
16431655
return nullptr;
16441656
}
16451657
if (isa<UndefValue>(Operands[0])) {
1646-
// cosine(arg) is between -1 and 1. cosine(invalid arg) is NaN
1647-
if (IntrinsicID == Intrinsic::cos)
1658+
// cosine(arg) is between -1 and 1. cosine(invalid arg) is NaN.
1659+
// ctpop() is between 0 and bitwidth, pick 0 for undef.
1660+
if (IntrinsicID == Intrinsic::cos ||
1661+
IntrinsicID == Intrinsic::ctpop)
16481662
return Constant::getNullValue(Ty);
16491663
if (IntrinsicID == Intrinsic::bswap ||
16501664
IntrinsicID == Intrinsic::bitreverse ||
@@ -1995,62 +2009,92 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
19952009
return nullptr;
19962010
}
19972011

1998-
if (auto *Op1 = dyn_cast<ConstantInt>(Operands[0])) {
1999-
if (auto *Op2 = dyn_cast<ConstantInt>(Operands[1])) {
2012+
if (Operands[0]->getType()->isIntegerTy() &&
2013+
Operands[1]->getType()->isIntegerTy()) {
2014+
const APInt *C0, *C1;
2015+
if (!getConstIntOrUndef(Operands[0], C0) ||
2016+
!getConstIntOrUndef(Operands[1], C1))
2017+
return nullptr;
2018+
2019+
switch (IntrinsicID) {
2020+
default: break;
2021+
case Intrinsic::smul_with_overflow:
2022+
case Intrinsic::umul_with_overflow:
2023+
// Even if both operands are undef, we cannot fold muls to undef
2024+
// in the general case. For example, on i2 there are no inputs
2025+
// that would produce { i2 -1, i1 true } as the result.
2026+
if (!C0 || !C1)
2027+
return Constant::getNullValue(Ty);
2028+
LLVM_FALLTHROUGH;
2029+
case Intrinsic::sadd_with_overflow:
2030+
case Intrinsic::uadd_with_overflow:
2031+
case Intrinsic::ssub_with_overflow:
2032+
case Intrinsic::usub_with_overflow: {
2033+
if (!C0 || !C1)
2034+
return UndefValue::get(Ty);
2035+
2036+
APInt Res;
2037+
bool Overflow;
20002038
switch (IntrinsicID) {
2001-
default: break;
2039+
default: llvm_unreachable("Invalid case");
20022040
case Intrinsic::sadd_with_overflow:
2041+
Res = C0->sadd_ov(*C1, Overflow);
2042+
break;
20032043
case Intrinsic::uadd_with_overflow:
2044+
Res = C0->uadd_ov(*C1, Overflow);
2045+
break;
20042046
case Intrinsic::ssub_with_overflow:
2047+
Res = C0->ssub_ov(*C1, Overflow);
2048+
break;
20052049
case Intrinsic::usub_with_overflow:
2050+
Res = C0->usub_ov(*C1, Overflow);
2051+
break;
20062052
case Intrinsic::smul_with_overflow:
2007-
case Intrinsic::umul_with_overflow: {
2008-
APInt Res;
2009-
bool Overflow;
2010-
switch (IntrinsicID) {
2011-
default: llvm_unreachable("Invalid case");
2012-
case Intrinsic::sadd_with_overflow:
2013-
Res = Op1->getValue().sadd_ov(Op2->getValue(), Overflow);
2014-
break;
2015-
case Intrinsic::uadd_with_overflow:
2016-
Res = Op1->getValue().uadd_ov(Op2->getValue(), Overflow);
2017-
break;
2018-
case Intrinsic::ssub_with_overflow:
2019-
Res = Op1->getValue().ssub_ov(Op2->getValue(), Overflow);
2020-
break;
2021-
case Intrinsic::usub_with_overflow:
2022-
Res = Op1->getValue().usub_ov(Op2->getValue(), Overflow);
2023-
break;
2024-
case Intrinsic::smul_with_overflow:
2025-
Res = Op1->getValue().smul_ov(Op2->getValue(), Overflow);
2026-
break;
2027-
case Intrinsic::umul_with_overflow:
2028-
Res = Op1->getValue().umul_ov(Op2->getValue(), Overflow);
2029-
break;
2030-
}
2031-
Constant *Ops[] = {
2032-
ConstantInt::get(Ty->getContext(), Res),
2033-
ConstantInt::get(Type::getInt1Ty(Ty->getContext()), Overflow)
2034-
};
2035-
return ConstantStruct::get(cast<StructType>(Ty), Ops);
2036-
}
2037-
case Intrinsic::uadd_sat:
2038-
return ConstantInt::get(Ty, Op1->getValue().uadd_sat(Op2->getValue()));
2039-
case Intrinsic::sadd_sat:
2040-
return ConstantInt::get(Ty, Op1->getValue().sadd_sat(Op2->getValue()));
2041-
case Intrinsic::usub_sat:
2042-
return ConstantInt::get(Ty, Op1->getValue().usub_sat(Op2->getValue()));
2043-
case Intrinsic::ssub_sat:
2044-
return ConstantInt::get(Ty, Op1->getValue().ssub_sat(Op2->getValue()));
2045-
case Intrinsic::cttz:
2046-
if (Op2->isOne() && Op1->isZero()) // cttz(0, 1) is undef.
2047-
return UndefValue::get(Ty);
2048-
return ConstantInt::get(Ty, Op1->getValue().countTrailingZeros());
2049-
case Intrinsic::ctlz:
2050-
if (Op2->isOne() && Op1->isZero()) // ctlz(0, 1) is undef.
2051-
return UndefValue::get(Ty);
2052-
return ConstantInt::get(Ty, Op1->getValue().countLeadingZeros());
2053+
Res = C0->smul_ov(*C1, Overflow);
2054+
break;
2055+
case Intrinsic::umul_with_overflow:
2056+
Res = C0->umul_ov(*C1, Overflow);
2057+
break;
20532058
}
2059+
Constant *Ops[] = {
2060+
ConstantInt::get(Ty->getContext(), Res),
2061+
ConstantInt::get(Type::getInt1Ty(Ty->getContext()), Overflow)
2062+
};
2063+
return ConstantStruct::get(cast<StructType>(Ty), Ops);
2064+
}
2065+
case Intrinsic::uadd_sat:
2066+
case Intrinsic::sadd_sat:
2067+
if (!C0 && !C1)
2068+
return UndefValue::get(Ty);
2069+
if (!C0 || !C1)
2070+
return Constant::getAllOnesValue(Ty);
2071+
if (IntrinsicID == Intrinsic::uadd_sat)
2072+
return ConstantInt::get(Ty, C0->uadd_sat(*C1));
2073+
else
2074+
return ConstantInt::get(Ty, C0->sadd_sat(*C1));
2075+
case Intrinsic::usub_sat:
2076+
case Intrinsic::ssub_sat:
2077+
if (!C0 && !C1)
2078+
return UndefValue::get(Ty);
2079+
if (!C0 || !C1)
2080+
return Constant::getNullValue(Ty);
2081+
if (IntrinsicID == Intrinsic::usub_sat)
2082+
return ConstantInt::get(Ty, C0->usub_sat(*C1));
2083+
else
2084+
return ConstantInt::get(Ty, C0->ssub_sat(*C1));
2085+
case Intrinsic::cttz:
2086+
case Intrinsic::ctlz:
2087+
assert(C1 && "Must be constant int");
2088+
2089+
// cttz(0, 1) and ctlz(0, 1) are undef.
2090+
if (C1->isOneValue() && (!C0 || C0->isNullValue()))
2091+
return UndefValue::get(Ty);
2092+
if (!C0)
2093+
return Constant::getNullValue(Ty);
2094+
if (IntrinsicID == Intrinsic::cttz)
2095+
return ConstantInt::get(Ty, C0->countTrailingZeros());
2096+
else
2097+
return ConstantInt::get(Ty, C0->countLeadingZeros());
20542098
}
20552099

20562100
return nullptr;
@@ -2136,26 +2180,33 @@ Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, Type *Ty,
21362180
}
21372181

21382182
if (IntrinsicID == Intrinsic::fshl || IntrinsicID == Intrinsic::fshr) {
2139-
auto *C0 = dyn_cast<ConstantInt>(Operands[0]);
2140-
auto *C1 = dyn_cast<ConstantInt>(Operands[1]);
2141-
auto *C2 = dyn_cast<ConstantInt>(Operands[2]);
2142-
if (!(C0 && C1 && C2))
2183+
const APInt *C0, *C1, *C2;
2184+
if (!getConstIntOrUndef(Operands[0], C0) ||
2185+
!getConstIntOrUndef(Operands[1], C1) ||
2186+
!getConstIntOrUndef(Operands[2], C2))
21432187
return nullptr;
21442188

2189+
bool IsRight = IntrinsicID == Intrinsic::fshr;
2190+
if (!C2)
2191+
return Operands[IsRight ? 1 : 0];
2192+
if (!C0 && !C1)
2193+
return UndefValue::get(Ty);
2194+
21452195
// The shift amount is interpreted as modulo the bitwidth. If the shift
21462196
// amount is effectively 0, avoid UB due to oversized inverse shift below.
2147-
unsigned BitWidth = C0->getBitWidth();
2148-
unsigned ShAmt = C2->getValue().urem(BitWidth);
2149-
bool IsRight = IntrinsicID == Intrinsic::fshr;
2197+
unsigned BitWidth = C2->getBitWidth();
2198+
unsigned ShAmt = C2->urem(BitWidth);
21502199
if (!ShAmt)
2151-
return IsRight ? C1 : C0;
2200+
return Operands[IsRight ? 1 : 0];
21522201

2153-
// (X << ShlAmt) | (Y >> LshrAmt)
2154-
const APInt &X = C0->getValue();
2155-
const APInt &Y = C1->getValue();
2202+
// (C0 << ShlAmt) | (C1 >> LshrAmt)
21562203
unsigned LshrAmt = IsRight ? ShAmt : BitWidth - ShAmt;
21572204
unsigned ShlAmt = !IsRight ? ShAmt : BitWidth - ShAmt;
2158-
return ConstantInt::get(Ty->getContext(), X.shl(ShlAmt) | Y.lshr(LshrAmt));
2205+
if (!C0)
2206+
return ConstantInt::get(Ty, C1->lshr(LshrAmt));
2207+
if (!C1)
2208+
return ConstantInt::get(Ty, C0->shl(ShlAmt));
2209+
return ConstantInt::get(Ty, C0->shl(ShlAmt) | C1->lshr(LshrAmt));
21592210
}
21602211

21612212
return nullptr;

llvm/test/Analysis/ConstantFolding/bitcount.ll

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -74,44 +74,39 @@ define i33 @ctlz_zero_undefined() {
7474

7575
define i31 @ctpop_undef() {
7676
; CHECK-LABEL: @ctpop_undef(
77-
; CHECK-NEXT: [[X:%.*]] = call i31 @llvm.ctpop.i31(i31 undef)
78-
; CHECK-NEXT: ret i31 [[X]]
77+
; CHECK-NEXT: ret i31 0
7978
;
8079
%x = call i31 @llvm.ctpop.i31(i31 undef)
8180
ret i31 %x
8281
}
8382

8483
define i32 @cttz_undef_defined() {
8584
; CHECK-LABEL: @cttz_undef_defined(
86-
; CHECK-NEXT: [[X:%.*]] = call i32 @llvm.cttz.i32(i32 undef, i1 false)
87-
; CHECK-NEXT: ret i32 [[X]]
85+
; CHECK-NEXT: ret i32 0
8886
;
8987
%x = call i32 @llvm.cttz.i32(i32 undef, i1 false)
9088
ret i32 %x
9189
}
9290

9391
define i32 @cttz_undef_undefined() {
9492
; CHECK-LABEL: @cttz_undef_undefined(
95-
; CHECK-NEXT: [[X:%.*]] = call i32 @llvm.cttz.i32(i32 undef, i1 true)
96-
; CHECK-NEXT: ret i32 [[X]]
93+
; CHECK-NEXT: ret i32 undef
9794
;
9895
%x = call i32 @llvm.cttz.i32(i32 undef, i1 true)
9996
ret i32 %x
10097
}
10198

10299
define i33 @ctlz_undef_defined() {
103100
; CHECK-LABEL: @ctlz_undef_defined(
104-
; CHECK-NEXT: [[X:%.*]] = call i33 @llvm.ctlz.i33(i33 undef, i1 false)
105-
; CHECK-NEXT: ret i33 [[X]]
101+
; CHECK-NEXT: ret i33 0
106102
;
107103
%x = call i33 @llvm.ctlz.i33(i33 undef, i1 false)
108104
ret i33 %x
109105
}
110106

111107
define i33 @ctlz_undef_undefined() {
112108
; CHECK-LABEL: @ctlz_undef_undefined(
113-
; CHECK-NEXT: [[X:%.*]] = call i33 @llvm.ctlz.i33(i33 undef, i1 true)
114-
; CHECK-NEXT: ret i33 [[X]]
109+
; CHECK-NEXT: ret i33 undef
115110
;
116111
%x = call i33 @llvm.ctlz.i33(i33 undef, i1 true)
117112
ret i33 %x
@@ -127,8 +122,7 @@ define <2 x i31> @ctpop_vector() {
127122

128123
define <2 x i31> @ctpop_vector_undef() {
129124
; CHECK-LABEL: @ctpop_vector_undef(
130-
; CHECK-NEXT: [[X:%.*]] = call <2 x i31> @llvm.ctpop.v2i31(<2 x i31> <i31 0, i31 undef>)
131-
; CHECK-NEXT: ret <2 x i31> [[X]]
125+
; CHECK-NEXT: ret <2 x i31> zeroinitializer
132126
;
133127
%x = call <2 x i31> @llvm.ctpop.v2i31(<2 x i31> <i31 0, i31 undef>)
134128
ret <2 x i31> %x
@@ -144,17 +138,15 @@ define <2 x i32> @cttz_vector() {
144138

145139
define <2 x i32> @cttz_vector_undef_defined() {
146140
; CHECK-LABEL: @cttz_vector_undef_defined(
147-
; CHECK-NEXT: [[X:%.*]] = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> <i32 0, i32 undef>, i1 false)
148-
; CHECK-NEXT: ret <2 x i32> [[X]]
141+
; CHECK-NEXT: ret <2 x i32> <i32 32, i32 0>
149142
;
150143
%x = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> <i32 0, i32 undef>, i1 false)
151144
ret <2 x i32> %x
152145
}
153146

154147
define <2 x i32> @cttz_vector_undef_undefined() {
155148
; CHECK-LABEL: @cttz_vector_undef_undefined(
156-
; CHECK-NEXT: [[X:%.*]] = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> <i32 0, i32 undef>, i1 true)
157-
; CHECK-NEXT: ret <2 x i32> [[X]]
149+
; CHECK-NEXT: ret <2 x i32> undef
158150
;
159151
%x = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> <i32 0, i32 undef>, i1 true)
160152
ret <2 x i32> %x
@@ -170,17 +162,15 @@ define <2 x i33> @ctlz_vector() {
170162

171163
define <2 x i33> @ctlz_vector_undef_defined() {
172164
; CHECK-LABEL: @ctlz_vector_undef_defined(
173-
; CHECK-NEXT: [[X:%.*]] = call <2 x i33> @llvm.ctlz.v2i33(<2 x i33> <i33 0, i33 undef>, i1 false)
174-
; CHECK-NEXT: ret <2 x i33> [[X]]
165+
; CHECK-NEXT: ret <2 x i33> <i33 33, i33 0>
175166
;
176167
%x = call <2 x i33> @llvm.ctlz.v2i33(<2 x i33> <i33 0, i33 undef>, i1 false)
177168
ret <2 x i33> %x
178169
}
179170

180171
define <2 x i33> @ctlz_vector_undef_undefined() {
181172
; CHECK-LABEL: @ctlz_vector_undef_undefined(
182-
; CHECK-NEXT: [[X:%.*]] = call <2 x i33> @llvm.ctlz.v2i33(<2 x i33> <i33 0, i33 undef>, i1 true)
183-
; CHECK-NEXT: ret <2 x i33> [[X]]
173+
; CHECK-NEXT: ret <2 x i33> undef
184174
;
185175
%x = call <2 x i33> @llvm.ctlz.v2i33(<2 x i33> <i33 0, i33 undef>, i1 true)
186176
ret <2 x i33> %x

0 commit comments

Comments
 (0)