Skip to content

Commit 7686d49

Browse files
committed
[ValueTracking] Handle returned attribute with mismatched type
The returned attribute can be used when it is possible to "losslessly bitcast" between the argument and return type, including between two vector types. computeKnownBits() would crash in this case, isKnownNonZero() would potentially produce a miscompile. Fixes #74722.
1 parent 46a5693 commit 7686d49

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,8 +1465,10 @@ static void computeKnownBitsFromOperator(const Operator *I,
14651465
Q.IIQ.getMetadata(cast<Instruction>(I), LLVMContext::MD_range))
14661466
computeKnownBitsFromRangeMetadata(*MD, Known);
14671467
if (const Value *RV = cast<CallBase>(I)->getReturnedArgOperand()) {
1468-
computeKnownBits(RV, Known2, Depth + 1, Q);
1469-
Known = Known.unionWith(Known2);
1468+
if (RV->getType() == I->getType()) {
1469+
computeKnownBits(RV, Known2, Depth + 1, Q);
1470+
Known = Known.unionWith(Known2);
1471+
}
14701472
}
14711473
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
14721474
switch (II->getIntrinsicID()) {
@@ -2712,7 +2714,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
27122714
if (const auto *RP = getArgumentAliasingToReturnedPointer(Call, true))
27132715
return isKnownNonZero(RP, Depth, Q);
27142716
} else if (const Value *RV = cast<CallBase>(I)->getReturnedArgOperand()) {
2715-
if (isKnownNonZero(RV, Depth, Q))
2717+
if (RV->getType() == I->getType() && isKnownNonZero(RV, Depth, Q))
27162718
return true;
27172719
}
27182720

llvm/test/Transforms/InstSimplify/returned.ll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,31 @@ define i1 @gep3() {
2525
ret i1 %equal
2626
}
2727

28+
define <8 x i1> @returned_vec_arg_casted(<2 x i32> %a) {
29+
; CHECK-LABEL: @returned_vec_arg_casted(
30+
; CHECK-NEXT: [[X:%.*]] = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> [[A:%.*]])
31+
; CHECK-NEXT: [[C:%.*]] = icmp slt <8 x i8> [[X]], zeroinitializer
32+
; CHECK-NEXT: ret <8 x i1> [[C]]
33+
;
34+
%x = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> %a)
35+
%C = icmp slt <8 x i8> %x, zeroinitializer
36+
ret <8 x i1> %C
37+
}
38+
39+
define <8 x i1> @returned_vec_arg_casted2(<2 x i32> %a) {
40+
; CHECK-LABEL: @returned_vec_arg_casted2(
41+
; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[A:%.*]], <i32 1, i32 1>
42+
; CHECK-NEXT: [[X:%.*]] = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> [[OR]])
43+
; CHECK-NEXT: [[C:%.*]] = icmp ne <8 x i8> [[X]], zeroinitializer
44+
; CHECK-NEXT: ret <8 x i1> [[C]]
45+
;
46+
%or = or <2 x i32> %a, <i32 1, i32 1>
47+
%x = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> %or)
48+
%C = icmp ne <8 x i8> %x, zeroinitializer
49+
ret <8 x i1> %C
50+
}
51+
52+
declare <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> returned)
2853
declare ptr @func1(ptr returned) nounwind readnone willreturn
2954
declare ptr @func2(ptr returned) nounwind readnone willreturn
3055

0 commit comments

Comments
 (0)