[llvm] [InstCombine] Use InstSimplify in FoldOpIntoSelect (PR #116073)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 14 08:01:19 PST 2024
https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/116073
>From 4b378746a5cc858926a6ad84469f3ded425efb8d Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 13 Nov 2024 14:30:18 +0100
Subject: [PATCH 1/2] [InstCombine] Use InstSimplify in FoldOpIntoSelect
Instead of only trying to constant fold the select arms, try to
simplify them.
---
.../InstCombine/InstructionCombining.cpp | 36 ++++++++-----------
.../Transforms/InstCombine/cast-mul-select.ll | 8 ++---
.../InstCombine/extract-select-agg.ll | 9 ++---
llvm/test/Transforms/InstCombine/fptrunc.ll | 6 ++--
.../Transforms/InstCombine/known-never-nan.ll | 15 ++++----
llvm/test/Transforms/InstCombine/select.ll | 21 +++++------
.../AArch64/deterministic-type-shrinkage.ll | 9 +++--
7 files changed, 44 insertions(+), 60 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 563b45de49836f..e2c974fbb9fdee 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1649,31 +1649,26 @@ Instruction *InstCombinerImpl::foldBinopOfSextBoolToSelect(BinaryOperator &BO) {
return SelectInst::Create(X, TVal, FVal);
}
-static Constant *constantFoldOperationIntoSelectOperand(Instruction &I,
- SelectInst *SI,
- bool IsTrueArm) {
- SmallVector<Constant *> ConstOps;
+static Value *simplifyOperationIntoSelectOperand(Instruction &I, SelectInst *SI,
+ bool IsTrueArm) {
+ SmallVector<Value *> Ops;
for (Value *Op : I.operands()) {
- Constant *C = nullptr;
+ Value *V = nullptr;
if (Op == SI) {
- C = dyn_cast<Constant>(IsTrueArm ? SI->getTrueValue()
- : SI->getFalseValue());
+ V = IsTrueArm ? SI->getTrueValue() : SI->getFalseValue();
} else if (match(SI->getCondition(),
m_SpecificICmp(IsTrueArm ? ICmpInst::ICMP_EQ
: ICmpInst::ICMP_NE,
- m_Specific(Op), m_Constant(C))) &&
- isGuaranteedNotToBeUndefOrPoison(C)) {
+ m_Specific(Op), m_Value(V))) &&
+ isGuaranteedNotToBeUndefOrPoison(V)) {
// Pass
} else {
- C = dyn_cast<Constant>(Op);
+ V = Op;
}
- if (C == nullptr)
- return nullptr;
-
- ConstOps.push_back(C);
+ Ops.push_back(V);
}
- return ConstantFoldInstOperands(&I, ConstOps, I.getDataLayout());
+ return simplifyInstructionWithOperands(&I, Ops, I.getDataLayout());
}
static Value *foldOperationIntoSelectOperand(Instruction &I, SelectInst *SI,
@@ -1681,7 +1676,7 @@ static Value *foldOperationIntoSelectOperand(Instruction &I, SelectInst *SI,
Instruction *Clone = I.clone();
Clone->replaceUsesOfWith(SI, NewOp);
Clone->dropUBImplyingAttrsAndMetadata();
- IC.InsertNewInstBefore(Clone, SI->getIterator());
+ IC.InsertNewInstBefore(Clone, I.getIterator());
return Clone;
}
@@ -1693,8 +1688,6 @@ Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
Value *TV = SI->getTrueValue();
Value *FV = SI->getFalseValue();
- if (!(isa<Constant>(TV) || isa<Constant>(FV)))
- return nullptr;
// Bool selects with constant operands can be folded to logical ops.
if (SI->getType()->isIntOrIntVectorTy(1))
@@ -1715,9 +1708,10 @@ Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
}
}
- // Make sure that one of the select arms constant folds successfully.
- Value *NewTV = constantFoldOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ true);
- Value *NewFV = constantFoldOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ false);
+ // Make sure that one of the select arms folds successfully.
+ Value *NewTV = simplifyOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ true);
+ Value *NewFV =
+ simplifyOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ false);
if (!NewTV && !NewFV)
return nullptr;
diff --git a/llvm/test/Transforms/InstCombine/cast-mul-select.ll b/llvm/test/Transforms/InstCombine/cast-mul-select.ll
index 6eb3a8c0a2049b..7999aa5e8ae075 100644
--- a/llvm/test/Transforms/InstCombine/cast-mul-select.ll
+++ b/llvm/test/Transforms/InstCombine/cast-mul-select.ll
@@ -73,10 +73,10 @@ define i8 @select2(i1 %cond, i8 %x, i8 %y, i8 %z) {
; DBGINFO-NEXT: #dbg_value(i8 [[Z:%.*]], [[META39:![0-9]+]], !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_stack_value), [[META45:![0-9]+]])
; DBGINFO-NEXT: [[D:%.*]] = add i8 [[X]], [[Y]], !dbg [[DBG46:![0-9]+]]
; DBGINFO-NEXT: #dbg_value(!DIArgList(i8 [[X]], i8 [[Y]]), [[META40:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_arg, 1, DW_OP_LLVM_convert, 8, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_plus, DW_OP_stack_value), [[DBG46]])
-; DBGINFO-NEXT: [[E:%.*]] = select i1 [[COND:%.*]], i8 [[Z]], i8 [[D]], !dbg [[DBG47:![0-9]+]]
-; DBGINFO-NEXT: #dbg_value(i32 poison, [[META41:![0-9]+]], !DIExpression(), [[DBG47]])
-; DBGINFO-NEXT: #dbg_value(i8 [[E]], [[META42:![0-9]+]], !DIExpression(), [[META48:![0-9]+]])
-; DBGINFO-NEXT: ret i8 [[E]], !dbg [[DBG49:![0-9]+]]
+; DBGINFO-NEXT: #dbg_value(i32 poison, [[META41:![0-9]+]], !DIExpression(), [[META47:![0-9]+]])
+; DBGINFO-NEXT: [[F:%.*]] = select i1 [[COND:%.*]], i8 [[Z]], i8 [[D]], !dbg [[META47]]
+; DBGINFO-NEXT: #dbg_value(i8 [[F]], [[META42:![0-9]+]], !DIExpression(), [[META48:![0-9]+]])
+; DBGINFO-NEXT: ret i8 [[F]], !dbg [[DBG49:![0-9]+]]
;
%A = zext i8 %x to i32
%B = zext i8 %y to i32
diff --git a/llvm/test/Transforms/InstCombine/extract-select-agg.ll b/llvm/test/Transforms/InstCombine/extract-select-agg.ll
index 6ba6b1a575601d..83b17c93620502 100644
--- a/llvm/test/Transforms/InstCombine/extract-select-agg.ll
+++ b/llvm/test/Transforms/InstCombine/extract-select-agg.ll
@@ -56,14 +56,9 @@ define void @test_select_agg_multiuse(i1 %cond, i64 %v1, i64 %v2, i64 %v3, i64 %
; CHECK-LABEL: define void @test_select_agg_multiuse(
; CHECK-SAME: i1 [[COND:%.*]], i64 [[V1:%.*]], i64 [[V2:%.*]], i64 [[V3:%.*]], i64 [[V4:%.*]]) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[A0:%.*]] = insertvalue { i64, i64 } poison, i64 [[V1]], 0
-; CHECK-NEXT: [[A1:%.*]] = insertvalue { i64, i64 } [[A0]], i64 [[V2]], 1
-; CHECK-NEXT: [[B0:%.*]] = insertvalue { i64, i64 } poison, i64 [[V3]], 0
-; CHECK-NEXT: [[B1:%.*]] = insertvalue { i64, i64 } [[B0]], i64 [[V4]], 1
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], { i64, i64 } [[A1]], { i64, i64 } [[B1]]
-; CHECK-NEXT: [[X:%.*]] = extractvalue { i64, i64 } [[SEL]], 0
+; CHECK-NEXT: [[X:%.*]] = select i1 [[COND]], i64 [[V1]], i64 [[V3]]
; CHECK-NEXT: call void @use(i64 [[X]])
-; CHECK-NEXT: [[Y:%.*]] = extractvalue { i64, i64 } [[SEL]], 1
+; CHECK-NEXT: [[Y:%.*]] = select i1 [[COND]], i64 [[V2]], i64 [[V4]]
; CHECK-NEXT: call void @use(i64 [[Y]])
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/InstCombine/fptrunc.ll b/llvm/test/Transforms/InstCombine/fptrunc.ll
index 825868b1070336..f46940ff060d41 100644
--- a/llvm/test/Transforms/InstCombine/fptrunc.ll
+++ b/llvm/test/Transforms/InstCombine/fptrunc.ll
@@ -52,7 +52,7 @@ define <2 x half> @fmul_constant_op1(<2 x float> %x) {
define float @fptrunc_select_true_val(float %x, double %y, i1 %cond) {
; CHECK-LABEL: @fptrunc_select_true_val(
; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[Y:%.*]] to float
-; CHECK-NEXT: [[NARROW_SEL:%.*]] = select fast i1 [[COND:%.*]], float [[TMP1]], float [[X:%.*]]
+; CHECK-NEXT: [[NARROW_SEL:%.*]] = select i1 [[COND:%.*]], float [[TMP1]], float [[X:%.*]]
; CHECK-NEXT: ret float [[NARROW_SEL]]
;
%e = fpext float %x to double
@@ -64,7 +64,7 @@ define float @fptrunc_select_true_val(float %x, double %y, i1 %cond) {
define <2 x float> @fptrunc_select_false_val(<2 x float> %x, <2 x double> %y, <2 x i1> %cond) {
; CHECK-LABEL: @fptrunc_select_false_val(
; CHECK-NEXT: [[TMP1:%.*]] = fptrunc <2 x double> [[Y:%.*]] to <2 x float>
-; CHECK-NEXT: [[NARROW_SEL:%.*]] = select nnan <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[TMP1]]
+; CHECK-NEXT: [[NARROW_SEL:%.*]] = select <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[TMP1]]
; CHECK-NEXT: ret <2 x float> [[NARROW_SEL]]
;
%e = fpext <2 x float> %x to <2 x double>
@@ -80,7 +80,7 @@ define half @fptrunc_select_true_val_extra_use(half %x, float %y, i1 %cond) {
; CHECK-NEXT: [[E:%.*]] = fpext half [[X:%.*]] to float
; CHECK-NEXT: call void @use(float [[E]])
; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[Y:%.*]] to half
-; CHECK-NEXT: [[NARROW_SEL:%.*]] = select ninf i1 [[COND:%.*]], half [[TMP1]], half [[X]]
+; CHECK-NEXT: [[NARROW_SEL:%.*]] = select i1 [[COND:%.*]], half [[TMP1]], half [[X]]
; CHECK-NEXT: ret half [[NARROW_SEL]]
;
%e = fpext half %x to float
diff --git a/llvm/test/Transforms/InstCombine/known-never-nan.ll b/llvm/test/Transforms/InstCombine/known-never-nan.ll
index 1ca24671d65c49..c4ce8740296470 100644
--- a/llvm/test/Transforms/InstCombine/known-never-nan.ll
+++ b/llvm/test/Transforms/InstCombine/known-never-nan.ll
@@ -20,10 +20,10 @@ define i1 @fabs_sqrt_src_maybe_nan(double %arg0, double %arg1) {
define i1 @select_maybe_nan_lhs(i1 %cond, double %lhs, double %arg1) {
; CHECK-LABEL: @select_maybe_nan_lhs(
-; CHECK-NEXT: [[RHS:%.*]] = fadd nnan double [[ARG1:%.*]], 1.000000e+00
-; CHECK-NEXT: [[OP:%.*]] = select i1 [[COND:%.*]], double [[LHS:%.*]], double [[RHS]]
-; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00
-; CHECK-NEXT: ret i1 [[TMP]]
+; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP:%.*]], 0.000000e+00
+; CHECK-NEXT: [[NOT_COND:%.*]] = xor i1 [[COND:%.*]], true
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[NOT_COND]], i1 true, i1 [[TMP]]
+; CHECK-NEXT: ret i1 [[TMP1]]
;
%rhs = fadd nnan double %arg1, 1.0
%op = select i1 %cond, double %lhs, double %rhs
@@ -33,10 +33,9 @@ define i1 @select_maybe_nan_lhs(i1 %cond, double %lhs, double %arg1) {
define i1 @select_maybe_nan_rhs(i1 %cond, double %arg0, double %rhs) {
; CHECK-LABEL: @select_maybe_nan_rhs(
-; CHECK-NEXT: [[LHS:%.*]] = fadd nnan double [[ARG0:%.*]], 1.000000e+00
-; CHECK-NEXT: [[OP:%.*]] = select i1 [[COND:%.*]], double [[LHS]], double [[RHS:%.*]]
-; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP]], 0.000000e+00
-; CHECK-NEXT: ret i1 [[TMP]]
+; CHECK-NEXT: [[TMP:%.*]] = fcmp ord double [[OP:%.*]], 0.000000e+00
+; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND:%.*]], i1 true, i1 [[TMP]]
+; CHECK-NEXT: ret i1 [[TMP1]]
;
%lhs = fadd nnan double %arg0, 1.0
%op = select i1 %cond, double %lhs, double %rhs
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 2baf315c508eee..9e92d227ca447f 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -4732,10 +4732,9 @@ define i32 @pr99436(ptr align 4 dereferenceable(4) %ptr) {
define i8 @sel_trunc_simplify(i1 %c, i8 %x, i16 %y) {
; CHECK-LABEL: @sel_trunc_simplify(
-; CHECK-NEXT: [[X_EXT:%.*]] = zext i8 [[X:%.*]] to i16
-; CHECK-NEXT: [[Y:%.*]] = select i1 [[C:%.*]], i16 [[X_EXT]], i16 [[Y1:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = trunc i16 [[Y]] to i8
-; CHECK-NEXT: ret i8 [[TMP1]]
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i16 [[Y:%.*]] to i8
+; CHECK-NEXT: [[TRUNC:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]]
+; CHECK-NEXT: ret i8 [[TRUNC]]
;
%x.ext = zext i8 %x to i16
%sel = select i1 %c, i16 %x.ext, i16 %y
@@ -4745,10 +4744,10 @@ define i8 @sel_trunc_simplify(i1 %c, i8 %x, i16 %y) {
define i32 @sel_umin_simplify(i1 %c, i32 %x, i16 %y) {
; CHECK-LABEL: @sel_umin_simplify(
-; CHECK-NEXT: [[X:%.*]] = select i1 [[C:%.*]], i32 [[X1:%.*]], i32 0
; CHECK-NEXT: [[ARG2_EXT:%.*]] = zext i16 [[ARG2:%.*]] to i32
-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[ARG2_EXT]])
-; CHECK-NEXT: ret i32 [[TMP1]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X:%.*]], i32 [[ARG2_EXT]])
+; CHECK-NEXT: [[RES:%.*]] = select i1 [[C:%.*]], i32 [[TMP1]], i32 0
+; CHECK-NEXT: ret i32 [[RES]]
;
%sel = select i1 %c, i32 %x, i32 0
%y.ext = zext i16 %y to i32
@@ -4758,11 +4757,9 @@ define i32 @sel_umin_simplify(i1 %c, i32 %x, i16 %y) {
define i32 @sel_extractvalue_simplify(i1 %c, { i32, i32 } %agg1, i32 %x, i32 %y) {
; CHECK-LABEL: @sel_extractvalue_simplify(
-; CHECK-NEXT: [[AGG2_0:%.*]] = insertvalue { i32, i32 } poison, i32 [[X:%.*]], 0
-; CHECK-NEXT: [[AGG2_1:%.*]] = insertvalue { i32, i32 } [[AGG2_0]], i32 [[Y:%.*]], 1
-; CHECK-NEXT: [[AGG1:%.*]] = select i1 [[C:%.*]], { i32, i32 } [[AGG2:%.*]], { i32, i32 } [[AGG2_1]]
-; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i32 } [[AGG1]], 1
-; CHECK-NEXT: ret i32 [[TMP1]]
+; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i32 } [[AGG1:%.*]], 1
+; CHECK-NEXT: [[RES:%.*]] = select i1 [[C:%.*]], i32 [[TMP1]], i32 [[Y:%.*]]
+; CHECK-NEXT: ret i32 [[RES]]
;
%agg2.0 = insertvalue { i32, i32 } poison, i32 %x, 0
%agg2.1 = insertvalue { i32, i32 } %agg2.0, i32 %y, 1
diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/deterministic-type-shrinkage.ll b/llvm/test/Transforms/LoopVectorize/AArch64/deterministic-type-shrinkage.ll
index 2ba460255c607d..7642d0d36be7b7 100644
--- a/llvm/test/Transforms/LoopVectorize/AArch64/deterministic-type-shrinkage.ll
+++ b/llvm/test/Transforms/LoopVectorize/AArch64/deterministic-type-shrinkage.ll
@@ -393,7 +393,6 @@ define void @replicate_operands_in_with_operands_in_minbws(ptr %dst, ptr noalias
; CHECK-LABEL: define void @replicate_operands_in_with_operands_in_minbws
; CHECK-SAME: (ptr [[DST:%.*]], ptr noalias [[SRC_1:%.*]], ptr noalias [[SRC_2:%.*]], i32 [[X:%.*]]) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X]], 65526
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
; CHECK: loop.header:
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
@@ -405,10 +404,10 @@ define void @replicate_operands_in_with_operands_in_minbws(ptr %dst, ptr noalias
; CHECK-NEXT: [[GEP_SRC_2:%.*]] = getelementptr inbounds i16, ptr [[SRC_2]], i64 [[IV]]
; CHECK-NEXT: [[L_2:%.*]] = load i16, ptr [[GEP_SRC_2]], align 2
; CHECK-NEXT: [[C_2:%.*]] = icmp ult i16 [[L_2]], 100
-; CHECK-NEXT: [[CONV:%.*]] = zext i16 [[L_2]] to i32
-; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C_2]], i32 [[SUB]], i32 [[CONV]]
-; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[SEL]] to i16
-; CHECK-NEXT: [[TRUNC:%.*]] = add i16 [[L_2]], [[TMP0]]
+; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[X]] to i16
+; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], -10
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C_2]], i16 [[TMP1]], i16 [[L_2]]
+; CHECK-NEXT: [[TRUNC:%.*]] = add i16 [[TMP2]], [[L_2]]
; CHECK-NEXT: [[GEP_DST:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 [[IV]]
; CHECK-NEXT: store i16 [[TRUNC]], ptr [[GEP_DST]], align 2
; CHECK-NEXT: br label [[LOOP_LATCH]]
>From dee0e6368f0a85bd7a9874bc13a866341611d44d Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Thu, 14 Nov 2024 10:22:53 +0100
Subject: [PATCH 2/2] style
---
llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index e2c974fbb9fdee..32f2a30afad48f 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1709,9 +1709,9 @@ Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
}
// Make sure that one of the select arms folds successfully.
- Value *NewTV = simplifyOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ true);
+ Value *NewTV = simplifyOperationIntoSelectOperand(Op, SI, /*IsTrueArm=*/true);
Value *NewFV =
- simplifyOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ false);
+ simplifyOperationIntoSelectOperand(Op, SI, /*IsTrueArm=*/false);
if (!NewTV && !NewFV)
return nullptr;
More information about the llvm-commits
mailing list