[llvm] cd31cf5 - [InstSimplify] Fix or disjoint miscompile with op replacement
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 1 02:45:20 PST 2023
Author: Nikita Popov
Date: 2023-12-01T11:45:09+01:00
New Revision: cd31cf5989aaf6a187aaf3af4f94207c55a70d0f
URL: https://github.com/llvm/llvm-project/commit/cd31cf5989aaf6a187aaf3af4f94207c55a70d0f
DIFF: https://github.com/llvm/llvm-project/commit/cd31cf5989aaf6a187aaf3af4f94207c55a70d0f.diff
LOG: [InstSimplify] Fix or disjoint miscompile with op replacement
Make sure %x does not get folded to "or disjoint %x, %x" without
dropping the flag, as this would be a derefinement.
Added:
Modified:
llvm/lib/Analysis/InstructionSimplify.cpp
llvm/test/Transforms/InstCombine/select.ll
llvm/test/Transforms/InstSimplify/select.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 9f3b3f25ec3f154..cef9f6ec179ba59 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4331,8 +4331,17 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
// x & x -> x, x | x -> x
if ((Opcode == Instruction::And || Opcode == Instruction::Or) &&
- NewOps[0] == NewOps[1])
+ NewOps[0] == NewOps[1]) {
+ // or disjoint x, x results in poison.
+ if (auto *PDI = dyn_cast<PossiblyDisjointInst>(BO)) {
+ if (PDI->isDisjoint()) {
+ if (!DropFlags)
+ return nullptr;
+ DropFlags->push_back(BO);
+ }
+ }
return NewOps[0];
+ }
// x - x -> 0, x ^ x -> 0. This is non-refining, because x is non-poison
// by assumption and this case never wraps, so nowrap flags can be
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index f1ccd4747bd1ce1..6f24758effac2fa 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -2916,10 +2916,9 @@ define i8 @replace_false_op_eq_shl_or_disjoint(i8 %x) {
ret i8 %sel
}
-; FIXME: This is a miscompile.
define i8 @select_or_disjoint_eq(i8 %x, i8 %y) {
; CHECK-LABEL: @select_or_disjoint_eq(
-; CHECK-NEXT: [[OR:%.*]] = or disjoint i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i8 [[OR]]
;
%cmp = icmp eq i8 %x, %y
diff --git a/llvm/test/Transforms/InstSimplify/select.ll b/llvm/test/Transforms/InstSimplify/select.ll
index 473d8b8b0368084..b9c79f02245ccff 100644
--- a/llvm/test/Transforms/InstSimplify/select.ll
+++ b/llvm/test/Transforms/InstSimplify/select.ll
@@ -1725,11 +1725,12 @@ define i8 @select_or_eq(i8 %x, i8 %y) {
ret i8 %sel
}
-; FIXME: This is a miscompile.
define i8 @select_or_disjoint_eq(i8 %x, i8 %y) {
; CHECK-LABEL: @select_or_disjoint_eq(
-; CHECK-NEXT: [[OR:%.*]] = or disjoint i8 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: ret i8 [[OR]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or disjoint i8 [[X]], [[Y]]
+; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[OR]]
+; CHECK-NEXT: ret i8 [[SEL]]
;
%cmp = icmp eq i8 %x, %y
%or = or disjoint i8 %x, %y
More information about the llvm-commits
mailing list