[llvm] 395c737 - [SimplifyCFG] Update SimplifyBranchOnICmpChain to recognize select form of and/or
Juneyoung Lee via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 18 15:54:19 PST 2021
Author: Juneyoung Lee
Date: 2021-01-19T08:53:40+09:00
New Revision: 395c737d9fcefb0fb99ac6c524b1d47e697d31d6
URL: https://github.com/llvm/llvm-project/commit/395c737d9fcefb0fb99ac6c524b1d47e697d31d6
DIFF: https://github.com/llvm/llvm-project/commit/395c737d9fcefb0fb99ac6c524b1d47e697d31d6.diff
LOG: [SimplifyCFG] Update SimplifyBranchOnICmpChain to recognize select form of and/or
This patch teaches SimplifyCFG::SimplifyBranchOnICmpChain to understand select form of
(x == C1 || x == C2 || ...) / (x != C1 && x != C2 && ...) and optimize them into switch if possible.
D93065 has more context about the transition, including links to the list of optimizations being updated.
Differential Revision: https://reviews.llvm.org/D93943
Added:
Modified:
llvm/lib/Transforms/Utils/SimplifyCFG.cpp
llvm/test/Transforms/SimplifyCFG/switch_create.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 7fe33fd3c759..a243a2e37950 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -692,7 +692,7 @@ struct ConstantComparesGatherer {
/// vector.
/// One "Extra" case is allowed to
diff er from the other.
void gather(Value *V) {
- bool isEQ = (cast<Instruction>(V)->getOpcode() == Instruction::Or);
+ bool isEQ = match(V, m_LogicalOr(m_Value(), m_Value()));
// Keep a stack (SmallVector for efficiency) for depth-first traversal
SmallVector<Value *, 8> DFT;
@@ -707,11 +707,14 @@ struct ConstantComparesGatherer {
if (Instruction *I = dyn_cast<Instruction>(V)) {
// If it is a || (or && depending on isEQ), process the operands.
- if (I->getOpcode() == (isEQ ? Instruction::Or : Instruction::And)) {
- if (Visited.insert(I->getOperand(1)).second)
- DFT.push_back(I->getOperand(1));
- if (Visited.insert(I->getOperand(0)).second)
- DFT.push_back(I->getOperand(0));
+ Value *Op0, *Op1;
+ if (isEQ ? match(I, m_LogicalOr(m_Value(Op0), m_Value(Op1)))
+ : match(I, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))) {
+ if (Visited.insert(Op1).second)
+ DFT.push_back(Op1);
+ if (Visited.insert(Op0).second)
+ DFT.push_back(Op0);
+
continue;
}
@@ -4147,7 +4150,7 @@ bool SimplifyCFGOpt::SimplifyBranchOnICmpChain(BranchInst *BI,
if (UsedICmps <= 1)
return false;
- bool TrueWhenEqual = (Cond->getOpcode() == Instruction::Or);
+ bool TrueWhenEqual = match(Cond, m_LogicalOr(m_Value(), m_Value()));
// There might be duplicate constants in the list, which the switch
// instruction can't handle, remove them now.
diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
index a4c84a66cafb..3a047313b44a 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
@@ -33,10 +33,10 @@ F: ; preds = %0
define void @test1_select(i32 %V) {
; CHECK-LABEL: @test1_select(
-; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[V:%.*]], 4
-; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[V]], 17
-; CHECK-NEXT: [[CN:%.*]] = select i1 [[C1]], i1 true, i1 [[C2]]
-; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]]
+; CHECK-NEXT: switch i32 [[V:%.*]], label [[F:%.*]] [
+; CHECK-NEXT: i32 17, label [[T:%.*]]
+; CHECK-NEXT: i32 4, label [[T]]
+; CHECK-NEXT: ]
; CHECK: T:
; CHECK-NEXT: call void @foo1()
; CHECK-NEXT: ret void
@@ -135,10 +135,10 @@ F: ; preds = %0
define void @test2_select(i32 %V) {
; CHECK-LABEL: @test2_select(
-; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[V:%.*]], 4
-; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 [[V]], 17
-; CHECK-NEXT: [[CN:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false
-; CHECK-NEXT: br i1 [[CN]], label [[T:%.*]], label [[F:%.*]]
+; CHECK-NEXT: switch i32 [[V:%.*]], label [[T:%.*]] [
+; CHECK-NEXT: i32 17, label [[F:%.*]]
+; CHECK-NEXT: i32 4, label [[F]]
+; CHECK-NEXT: ]
; CHECK: T:
; CHECK-NEXT: call void @foo1()
; CHECK-NEXT: ret void
@@ -465,13 +465,17 @@ F:
define i32 @test10_select(i32 %mode, i1 %Cond) {
; CHECK-LABEL: @test10_select(
-; CHECK-NEXT: T:
-; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[MODE:%.*]], 0
-; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[MODE]], 51
-; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 [[B]], i1 false
-; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i1 [[COND:%.*]], i1 false
-; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 123, i32 324
-; CHECK-NEXT: ret i32 [[SPEC_SELECT]]
+; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]]
+; CHECK: switch.early.test:
+; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [
+; CHECK-NEXT: i32 51, label [[F]]
+; CHECK-NEXT: i32 0, label [[F]]
+; CHECK-NEXT: ]
+; CHECK: T:
+; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ]
+; CHECK-NEXT: ret i32 [[MERGE]]
+; CHECK: F:
+; CHECK-NEXT: br label [[T]]
;
%A = icmp ne i32 %mode, 0
%B = icmp ne i32 %mode, 51
@@ -488,13 +492,17 @@ F:
; TODO: %Cond doesn't need freeze
define i32 @test10_select_and(i32 %mode, i1 %Cond) {
; CHECK-LABEL: @test10_select_and(
-; CHECK-NEXT: T:
-; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[MODE:%.*]], 0
-; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[MODE]], 51
-; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 [[B]], i1 false
-; CHECK-NEXT: [[D:%.*]] = and i1 [[C]], [[COND:%.*]]
-; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 123, i32 324
-; CHECK-NEXT: ret i32 [[SPEC_SELECT]]
+; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]]
+; CHECK: switch.early.test:
+; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [
+; CHECK-NEXT: i32 51, label [[F]]
+; CHECK-NEXT: i32 0, label [[F]]
+; CHECK-NEXT: ]
+; CHECK: T:
+; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ]
+; CHECK-NEXT: ret i32 [[MERGE]]
+; CHECK: F:
+; CHECK-NEXT: br label [[T]]
;
%A = icmp ne i32 %mode, 0
%B = icmp ne i32 %mode, 51
@@ -510,13 +518,17 @@ F:
define i32 @test10_select_nofreeze(i32 %mode, i1 noundef %Cond) {
; CHECK-LABEL: @test10_select_nofreeze(
-; CHECK-NEXT: T:
-; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[MODE:%.*]], 0
-; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[MODE]], 51
-; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i1 [[B]], i1 false
-; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i1 [[COND:%.*]], i1 false
-; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 123, i32 324
-; CHECK-NEXT: ret i32 [[SPEC_SELECT]]
+; CHECK-NEXT: br i1 [[COND:%.*]], label [[SWITCH_EARLY_TEST:%.*]], label [[F:%.*]]
+; CHECK: switch.early.test:
+; CHECK-NEXT: switch i32 [[MODE:%.*]], label [[T:%.*]] [
+; CHECK-NEXT: i32 51, label [[F]]
+; CHECK-NEXT: i32 0, label [[F]]
+; CHECK-NEXT: ]
+; CHECK: T:
+; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 123, [[SWITCH_EARLY_TEST]] ], [ 324, [[F]] ]
+; CHECK-NEXT: ret i32 [[MERGE]]
+; CHECK: F:
+; CHECK-NEXT: br label [[T]]
;
%A = icmp ne i32 %mode, 0
%B = icmp ne i32 %mode, 51
@@ -903,11 +915,11 @@ else:
define void @test19_select(i32 %arg) {
; CHECK-LABEL: @test19_select(
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[ARG:%.*]], -2
-; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[AND]], 12
-; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[ARG]], 32
-; CHECK-NEXT: [[PRED:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]]
-; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[ELSE:%.*]] [
+; CHECK-NEXT: i32 32, label [[IF:%.*]]
+; CHECK-NEXT: i32 13, label [[IF]]
+; CHECK-NEXT: i32 12, label [[IF]]
+; CHECK-NEXT: ]
; CHECK: if:
; CHECK-NEXT: call void @foo1()
; CHECK-NEXT: ret void
More information about the llvm-commits
mailing list