From 7d25bcef0937e454bb2d3cf3b4ed615257951120 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 16 Dec 2024 21:11:59 +0800 Subject: [PATCH] [InstCombine] Recursively replace condition with constant in select arms (#120011) This patch is proposed to reduce the number of selects with undefs introduced by https://github.com/llvm/llvm-project/pull/119884. --- .../InstCombine/InstCombineSelect.cpp | 6 ++ llvm/test/Transforms/InstCombine/select.ll | 89 +++++++++++++++++-- 2 files changed, 89 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 50dfb58cadb17b..5eebfdb774d2e2 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3800,6 +3800,12 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) { ConstantInt::getFalse(CondType), SQ, /* AllowRefinement */ true)) return replaceOperand(SI, 2, S); + + if (replaceInInstruction(TrueVal, CondVal, + ConstantInt::getTrue(CondType)) || + replaceInInstruction(FalseVal, CondVal, + ConstantInt::getFalse(CondType))) + return &SI; } if (Instruction *R = foldSelectOfBools(SI)) diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll index 82c079d681284d..0168a804239a89 100644 --- a/llvm/test/Transforms/InstCombine/select.ll +++ b/llvm/test/Transforms/InstCombine/select.ll @@ -4580,9 +4580,8 @@ define i32 @src_select_xxory_eq0_xorxy_y(i32 %x, i32 %y) { define i32 @sequence_select_with_same_cond_false(i1 %c1, i1 %c2){ ; CHECK-LABEL: @sequence_select_with_same_cond_false( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1:%.*]], i32 23, i32 45 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[C2:%.*]], i32 666, i32 [[S1]] -; CHECK-NEXT: [[S3:%.*]] = select i1 [[C1]], i32 789, i32 [[S2]] +; CHECK-NEXT: [[S2:%.*]] = select i1 [[C2:%.*]], i32 666, i32 45 +; CHECK-NEXT: [[S3:%.*]] = select i1 [[C1:%.*]], i32 789, i32 [[S2]] ; CHECK-NEXT: ret i32 [[S3]] ; %s1 = select i1 %c1, i32 23, i32 45 @@ -4593,9 +4592,8 @@ define i32 @sequence_select_with_same_cond_false(i1 %c1, i1 %c2){ define i32 @sequence_select_with_same_cond_true(i1 %c1, i1 %c2){ ; CHECK-LABEL: @sequence_select_with_same_cond_true( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1:%.*]], i32 45, i32 23 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[C2:%.*]], i32 [[S1]], i32 666 -; CHECK-NEXT: [[S3:%.*]] = select i1 [[C1]], i32 [[S2]], i32 789 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[C2:%.*]], i32 45, i32 666 +; CHECK-NEXT: [[S3:%.*]] = select i1 [[C1:%.*]], i32 [[S2]], i32 789 ; CHECK-NEXT: ret i32 [[S3]] ; %s1 = select i1 %c1, i32 45, i32 23 @@ -4766,3 +4764,82 @@ define i32 @sel_extractvalue_simplify(i1 %c, { i32, i32 } %agg1, i32 %x, i32 %y) %res = extractvalue { i32, i32 } %sel, 1 ret i32 %res } + +define i1 @replace_select_cond_true(i1 %cond, i32 %v1, i32 %v2, i32 %v3) { +; CHECK-LABEL: @replace_select_cond_true( +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[SEL:%.*]], [[V2:%.*]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %sel = select i1 %cond, i32 %v1, i32 %v3 + %cmp = icmp eq i32 %sel, %v2 + %and = select i1 %cond, i1 %cmp, i1 false + ret i1 %and +} + +define i1 @replace_select_cond_false(i1 %cond, i32 %v1, i32 %v2, i32 %v3) { +; CHECK-LABEL: @replace_select_cond_false( +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[SEL:%.*]], [[V2:%.*]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[COND:%.*]], i1 true, i1 [[CMP]] +; CHECK-NEXT: ret i1 [[OR]] +; + %sel = select i1 %cond, i32 %v1, i32 %v3 + %cmp = icmp eq i32 %sel, %v2 + %or = select i1 %cond, i1 true, i1 %cmp + ret i1 %or +} + +define i32 @replace_and_cond(i1 %cond1, i1 %cond2) { +; CHECK-LABEL: @replace_and_cond( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[AND:%.*]], i32 3, i32 2 +; CHECK-NEXT: [[MUX:%.*]] = select i1 [[COND1:%.*]], i32 [[SEL]], i32 1 +; CHECK-NEXT: ret i32 [[MUX]] +; + %and = and i1 %cond1, %cond2 + %sel = select i1 %and, i32 3, i32 2 + %mux = select i1 %cond1, i32 %sel, i32 1 + ret i32 %mux +} + +define <2 x i32> @replace_and_cond_vec(<2 x i1> %cond1, <2 x i1> %cond2) { +; CHECK-LABEL: @replace_and_cond_vec( +; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[COND2:%.*]], <2 x i32> splat (i32 3), <2 x i32> splat (i32 2) +; CHECK-NEXT: [[MUX:%.*]] = select <2 x i1> [[COND1:%.*]], <2 x i32> [[SEL]], <2 x i32> splat (i32 1) +; CHECK-NEXT: ret <2 x i32> [[MUX]] +; + %and = and <2 x i1> %cond1, %cond2 + %sel = select <2 x i1> %and, <2 x i32> splat(i32 3), <2 x i32> splat(i32 2) + %mux = select <2 x i1> %cond1, <2 x i32> %sel, <2 x i32> splat(i32 1) + ret <2 x i32> %mux +} + +; TODO: We can still replace the use of %and with %cond2 +define i32 @replace_and_cond_multiuse1(i1 %cond1, i1 %cond2) { +; CHECK-LABEL: @replace_and_cond_multiuse1( +; CHECK-NEXT: [[AND:%.*]] = and i1 [[COND1:%.*]], [[COND2:%.*]] +; CHECK-NEXT: call void @use(i1 [[AND]]) +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[AND]], i32 3, i32 2 +; CHECK-NEXT: [[MUX:%.*]] = select i1 [[COND1]], i32 [[SEL]], i32 1 +; CHECK-NEXT: ret i32 [[MUX]] +; + %and = and i1 %cond1, %cond2 + call void @use(i1 %and) + %sel = select i1 %and, i32 3, i32 2 + %mux = select i1 %cond1, i32 %sel, i32 1 + ret i32 %mux +} + +define i32 @replace_and_cond_multiuse2(i1 %cond1, i1 %cond2) { +; CHECK-LABEL: @replace_and_cond_multiuse2( +; CHECK-NEXT: [[AND:%.*]] = and i1 [[COND1:%.*]], [[COND2:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[AND]], i32 3, i32 2 +; CHECK-NEXT: call void @use32(i32 [[SEL]]) +; CHECK-NEXT: [[MUX:%.*]] = select i1 [[COND1]], i32 [[SEL]], i32 1 +; CHECK-NEXT: ret i32 [[MUX]] +; + %and = and i1 %cond1, %cond2 + %sel = select i1 %and, i32 3, i32 2 + call void @use32(i32 %sel) + %mux = select i1 %cond1, i32 %sel, i32 1 + ret i32 %mux +}