Skip to content

Commit cd31cf5

Browse files
committed
[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.
1 parent 5a1020b commit cd31cf5

File tree

3 files changed

+15
-6
lines changed

3 files changed

+15
-6
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4331,8 +4331,17 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
43314331

43324332
// x & x -> x, x | x -> x
43334333
if ((Opcode == Instruction::And || Opcode == Instruction::Or) &&
4334-
NewOps[0] == NewOps[1])
4334+
NewOps[0] == NewOps[1]) {
4335+
// or disjoint x, x results in poison.
4336+
if (auto *PDI = dyn_cast<PossiblyDisjointInst>(BO)) {
4337+
if (PDI->isDisjoint()) {
4338+
if (!DropFlags)
4339+
return nullptr;
4340+
DropFlags->push_back(BO);
4341+
}
4342+
}
43354343
return NewOps[0];
4344+
}
43364345

43374346
// x - x -> 0, x ^ x -> 0. This is non-refining, because x is non-poison
43384347
// by assumption and this case never wraps, so nowrap flags can be

llvm/test/Transforms/InstCombine/select.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2916,10 +2916,9 @@ define i8 @replace_false_op_eq_shl_or_disjoint(i8 %x) {
29162916
ret i8 %sel
29172917
}
29182918

2919-
; FIXME: This is a miscompile.
29202919
define i8 @select_or_disjoint_eq(i8 %x, i8 %y) {
29212920
; CHECK-LABEL: @select_or_disjoint_eq(
2922-
; CHECK-NEXT: [[OR:%.*]] = or disjoint i8 [[X:%.*]], [[Y:%.*]]
2921+
; CHECK-NEXT: [[OR:%.*]] = or i8 [[X:%.*]], [[Y:%.*]]
29232922
; CHECK-NEXT: ret i8 [[OR]]
29242923
;
29252924
%cmp = icmp eq i8 %x, %y

llvm/test/Transforms/InstSimplify/select.ll

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,11 +1725,12 @@ define i8 @select_or_eq(i8 %x, i8 %y) {
17251725
ret i8 %sel
17261726
}
17271727

1728-
; FIXME: This is a miscompile.
17291728
define i8 @select_or_disjoint_eq(i8 %x, i8 %y) {
17301729
; CHECK-LABEL: @select_or_disjoint_eq(
1731-
; CHECK-NEXT: [[OR:%.*]] = or disjoint i8 [[X:%.*]], [[Y:%.*]]
1732-
; CHECK-NEXT: ret i8 [[OR]]
1730+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
1731+
; CHECK-NEXT: [[OR:%.*]] = or disjoint i8 [[X]], [[Y]]
1732+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[OR]]
1733+
; CHECK-NEXT: ret i8 [[SEL]]
17331734
;
17341735
%cmp = icmp eq i8 %x, %y
17351736
%or = or disjoint i8 %x, %y

0 commit comments

Comments
 (0)