Skip to content

Commit cfdc967

Browse files
[Instcombine] Fix uses of undef (PR46940)
Without this patch, we attempt to distribute And over Xor even in unsafe circumstances like so: undef & (true ^ true) ==> (undef & true) ^ (undef & true) and evaluate it to undef instead of false. Note that "true ^ true" may show up implicitly with one true being part of a PHI node. This patch fixes the problem by teaching SimplifyUsingDistributiveLaws to not use undef as part of simplifications. Reviewers: spatel, aqjune, nikic, lebedev.ri, fhahn, jdoerfert Differential Revision: https://reviews.llvm.org/D85687
1 parent 29429d1 commit cfdc967

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -740,8 +740,10 @@ Value *InstCombinerImpl::SimplifyUsingDistributiveLaws(BinaryOperator &I) {
740740
Value *A = Op0->getOperand(0), *B = Op0->getOperand(1), *C = RHS;
741741
Instruction::BinaryOps InnerOpcode = Op0->getOpcode(); // op'
742742

743-
Value *L = SimplifyBinOp(TopLevelOpcode, A, C, SQ.getWithInstruction(&I));
744-
Value *R = SimplifyBinOp(TopLevelOpcode, B, C, SQ.getWithInstruction(&I));
743+
// Disable the use of undef because it's not safe to distribute undef.
744+
auto SQDistributive = SQ.getWithInstruction(&I).getWithoutUndef();
745+
Value *L = SimplifyBinOp(TopLevelOpcode, A, C, SQDistributive);
746+
Value *R = SimplifyBinOp(TopLevelOpcode, B, C, SQDistributive);
745747

746748
// Do "A op C" and "B op C" both simplify?
747749
if (L && R) {
@@ -777,8 +779,10 @@ Value *InstCombinerImpl::SimplifyUsingDistributiveLaws(BinaryOperator &I) {
777779
Value *A = LHS, *B = Op1->getOperand(0), *C = Op1->getOperand(1);
778780
Instruction::BinaryOps InnerOpcode = Op1->getOpcode(); // op'
779781

780-
Value *L = SimplifyBinOp(TopLevelOpcode, A, B, SQ.getWithInstruction(&I));
781-
Value *R = SimplifyBinOp(TopLevelOpcode, A, C, SQ.getWithInstruction(&I));
782+
// Disable the use of undef because it's not safe to distribute undef.
783+
auto SQDistributive = SQ.getWithInstruction(&I).getWithoutUndef();
784+
Value *L = SimplifyBinOp(TopLevelOpcode, A, B, SQDistributive);
785+
Value *R = SimplifyBinOp(TopLevelOpcode, A, C, SQDistributive);
782786

783787
// Do "A op B" and "A op C" both simplify?
784788
if (L && R) {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: opt < %s -instcombine -S | FileCheck %s
2+
;
3+
; This test ensures that InstCombine does not distribute And over Xor
4+
; using simplifications involving undef.
5+
6+
define zeroext i1 @foo(i32 %arg) {
7+
; CHECK-LABEL: @foo(
8+
9+
entry:
10+
%cmp1 = icmp eq i32 %arg, 37
11+
br i1 %cmp1, label %bb_then, label %bb_else
12+
13+
bb_then:
14+
call void @bar()
15+
br label %bb_exit
16+
17+
bb_else:
18+
%cmp2 = icmp slt i32 %arg, 17
19+
br label %bb_exit
20+
21+
; CHECK: bb_exit:
22+
; CHECK-NEXT: [[PHI1:%.*]] = phi i1 [ [[CMP2:%.*]], [[BB_ELSE:%.*]] ], [ undef, [[BB_THEN:%.*]] ]
23+
; CHECK-NEXT: [[XOR1:%.*]] = xor i1 [[CMP1:%.*]], true
24+
; CHECK-NEXT: [[AND1:%.*]] = and i1 [[PHI1]], [[XOR1]]
25+
; CHECK-NEXT: ret i1 [[AND1]]
26+
bb_exit:
27+
%phi1 = phi i1 [ %cmp2, %bb_else ], [ undef, %bb_then ]
28+
%xor1 = xor i1 %cmp1, true
29+
%and1 = and i1 %phi1, %xor1
30+
ret i1 %and1
31+
}
32+
33+
declare void @bar()

0 commit comments

Comments
 (0)