aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <npopov@redhat.com>2023-12-08 17:02:48 +0100
committerNikita Popov <npopov@redhat.com>2023-12-08 17:05:13 +0100
commit7686d4951712468e354350b6d26aa70d052c8db4 (patch)
tree6f1a7ed3fb39c00cf751005c5211dd4591527ed9
parent46a56931251eba767929f6a2110da5b1bcbc5eb9 (diff)
downloadllvm-7686d4951712468e354350b6d26aa70d052c8db4.zip
llvm-7686d4951712468e354350b6d26aa70d052c8db4.tar.gz
llvm-7686d4951712468e354350b6d26aa70d052c8db4.tar.bz2
[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 https://github.com/llvm/llvm-project/issues/74722.
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp8
-rw-r--r--llvm/test/Transforms/InstSimplify/returned.ll25
2 files changed, 30 insertions, 3 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index eb2ee04..5445746 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1465,8 +1465,10 @@ static void computeKnownBitsFromOperator(const Operator *I,
Q.IIQ.getMetadata(cast<Instruction>(I), LLVMContext::MD_range))
computeKnownBitsFromRangeMetadata(*MD, Known);
if (const Value *RV = cast<CallBase>(I)->getReturnedArgOperand()) {
- computeKnownBits(RV, Known2, Depth + 1, Q);
- Known = Known.unionWith(Known2);
+ if (RV->getType() == I->getType()) {
+ computeKnownBits(RV, Known2, Depth + 1, Q);
+ Known = Known.unionWith(Known2);
+ }
}
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
switch (II->getIntrinsicID()) {
@@ -2712,7 +2714,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
if (const auto *RP = getArgumentAliasingToReturnedPointer(Call, true))
return isKnownNonZero(RP, Depth, Q);
} else if (const Value *RV = cast<CallBase>(I)->getReturnedArgOperand()) {
- if (isKnownNonZero(RV, Depth, Q))
+ if (RV->getType() == I->getType() && isKnownNonZero(RV, Depth, Q))
return true;
}
diff --git a/llvm/test/Transforms/InstSimplify/returned.ll b/llvm/test/Transforms/InstSimplify/returned.ll
index 94a98ac6..2da1052 100644
--- a/llvm/test/Transforms/InstSimplify/returned.ll
+++ b/llvm/test/Transforms/InstSimplify/returned.ll
@@ -25,6 +25,31 @@ define i1 @gep3() {
ret i1 %equal
}
+define <8 x i1> @returned_vec_arg_casted(<2 x i32> %a) {
+; CHECK-LABEL: @returned_vec_arg_casted(
+; CHECK-NEXT: [[X:%.*]] = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> [[A:%.*]])
+; CHECK-NEXT: [[C:%.*]] = icmp slt <8 x i8> [[X]], zeroinitializer
+; CHECK-NEXT: ret <8 x i1> [[C]]
+;
+ %x = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> %a)
+ %C = icmp slt <8 x i8> %x, zeroinitializer
+ ret <8 x i1> %C
+}
+
+define <8 x i1> @returned_vec_arg_casted2(<2 x i32> %a) {
+; CHECK-LABEL: @returned_vec_arg_casted2(
+; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[A:%.*]], <i32 1, i32 1>
+; CHECK-NEXT: [[X:%.*]] = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> [[OR]])
+; CHECK-NEXT: [[C:%.*]] = icmp ne <8 x i8> [[X]], zeroinitializer
+; CHECK-NEXT: ret <8 x i1> [[C]]
+;
+ %or = or <2 x i32> %a, <i32 1, i32 1>
+ %x = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> %or)
+ %C = icmp ne <8 x i8> %x, zeroinitializer
+ ret <8 x i1> %C
+}
+
+declare <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> returned)
declare ptr @func1(ptr returned) nounwind readnone willreturn
declare ptr @func2(ptr returned) nounwind readnone willreturn