Skip to content

Commit 115d2f6

Browse files
committed
[InstCombine] canonicalize branch with logical-and-not condition
https://alive2.llvm.org/ce/z/EfHlWN In the motivating case from issue #58313, this allows forming a duplicate 'not' op which then gets CSE'd and simplifyCFG'd and combined into the expected 'xor'.
1 parent a7265f9 commit 115d2f6

File tree

3 files changed

+17
-16
lines changed

3 files changed

+17
-16
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3180,13 +3180,22 @@ Instruction *InstCombinerImpl::visitBranchInst(BranchInst &BI) {
31803180

31813181
// Change br (not X), label True, label False to: br X, label False, True
31823182
Value *Cond = BI.getCondition();
3183-
Value *X = nullptr;
3183+
Value *X;
31843184
if (match(Cond, m_Not(m_Value(X))) && !isa<Constant>(X)) {
31853185
// Swap Destinations and condition...
31863186
BI.swapSuccessors();
31873187
return replaceOperand(BI, 0, X);
31883188
}
31893189

3190+
// br (X && !Y), T, F --> br ((X && Y) || !X), F, T
3191+
Value *Y;
3192+
if (isa<SelectInst>(Cond) &&
3193+
match(Cond, m_OneUse(m_LogicalAnd(m_Value(X), m_Not(m_Value(Y)))))) {
3194+
Value *AndOr = Builder.CreateSelect(X, Y, Builder.getTrue());
3195+
BI.swapSuccessors();
3196+
return replaceOperand(BI, 0, AndOr);
3197+
}
3198+
31903199
// If the condition is irrelevant, remove the use so that other
31913200
// transforms on the condition become more effective.
31923201
if (!isa<ConstantInt>(Cond) && BI.getSuccessor(0) == BI.getSuccessor(1))

llvm/test/Transforms/InstCombine/branch.ll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,14 @@ merge.2:
113113
ret i1 %merge.cond.2
114114
}
115115

116-
; if (x && !y) ret 42; ret 3
116+
; if (x && !y) ret 42; ret 3 --> if (!x || y) ret 3; ret 42
117117

118118
define i32 @logical_and_not(i1 %x, i1 %y) {
119119
; CHECK-LABEL: @logical_and_not(
120120
; CHECK-NEXT: entry:
121-
; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
122-
; CHECK-NEXT: [[AND:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false
123-
; CHECK-NEXT: br i1 [[AND]], label [[T:%.*]], label [[F:%.*]]
121+
; CHECK-NEXT: [[NOT_X:%.*]] = xor i1 [[X:%.*]], true
122+
; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[Y:%.*]]
123+
; CHECK-NEXT: br i1 [[TMP0]], label [[F:%.*]], label [[T:%.*]]
124124
; CHECK: t:
125125
; CHECK-NEXT: ret i32 42
126126
; CHECK: f:
@@ -138,7 +138,7 @@ f:
138138
ret i32 3
139139
}
140140

141-
; if (x && y || !x) ret 3; ret 42
141+
; if (x && y || !x) ret 3; ret 42 --> if (!x || y) ret 3; ret 42
142142

143143
define i32 @logical_and_or(i1 %x, i1 %y) {
144144
; CHECK-LABEL: @logical_and_or(

llvm/test/Transforms/PhaseOrdering/simplifycfg-options.ll

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,8 @@ end:
105105
define i1 @PR58313(i1 %lhs, i1 %rhs) {
106106
; CHECK-LABEL: @PR58313(
107107
; CHECK-NEXT: andandend:
108-
; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[RHS:%.*]], true
109-
; CHECK-NEXT: [[ANDANDVAL:%.*]] = select i1 [[LHS:%.*]], i1 [[TMP0]], i1 false
110-
; CHECK-NEXT: br i1 [[ANDANDVAL]], label [[OROREND:%.*]], label [[OROR:%.*]]
111-
; CHECK: oror:
112-
; CHECK-NEXT: [[TMP1:%.*]] = xor i1 [[LHS]], true
113-
; CHECK-NEXT: [[ANDANDVAL3:%.*]] = select i1 [[TMP1]], i1 [[RHS]], i1 false
114-
; CHECK-NEXT: br label [[OROREND]]
115-
; CHECK: ororend:
116-
; CHECK-NEXT: [[ORORVAL:%.*]] = phi i1 [ true, [[ANDANDEND:%.*]] ], [ [[ANDANDVAL3]], [[OROR]] ]
117-
; CHECK-NEXT: ret i1 [[ORORVAL]]
108+
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = xor i1 [[LHS:%.*]], [[RHS:%.*]]
109+
; CHECK-NEXT: ret i1 [[SPEC_SELECT]]
118110
;
119111
andandend:
120112
%0 = xor i1 %rhs, true

0 commit comments

Comments
 (0)