Skip to content

Commit

Permalink
[InstCombine] Make FoldOpIntoSelect handle non-constants and use co…
Browse files Browse the repository at this point in the history
…ndition to deduce constants.

Make the fold use the information present in the condition for deducing constants i.e:
```
%c = icmp eq i8 %x, 10
%s = select i1 %c, i8 3, i8 2
%r = mul i8 %x, %s
```

If we fold the `mul` into the select, on the true side we insert `10` for `%x` in the `mul`.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D146349
  • Loading branch information
goldsteinn committed Apr 14, 2023
1 parent db0706b commit 82f0827
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 17 deletions.
34 changes: 21 additions & 13 deletions llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Expand Up @@ -1028,21 +1028,29 @@ Instruction *InstCombinerImpl::foldBinopOfSextBoolToSelect(BinaryOperator &BO) {
return SelectInst::Create(X, TVal, FVal);
}

static Constant *constantFoldOperationIntoSelectOperand(
Instruction &I, SelectInst *SI, Value *SO) {
auto *ConstSO = dyn_cast<Constant>(SO);
if (!ConstSO)
return nullptr;

static Constant *constantFoldOperationIntoSelectOperand(Instruction &I,
SelectInst *SI,
bool IsTrueArm) {
SmallVector<Constant *> ConstOps;
for (Value *Op : I.operands()) {
if (Op == SI)
ConstOps.push_back(ConstSO);
else if (auto *C = dyn_cast<Constant>(Op))
ConstOps.push_back(C);
else
CmpInst::Predicate Pred;
Constant *C = nullptr;
if (Op == SI) {
C = dyn_cast<Constant>(IsTrueArm ? SI->getTrueValue()
: SI->getFalseValue());
} else if (match(SI->getCondition(),
m_ICmp(Pred, m_Specific(Op), m_Constant(C))) &&
Pred == (IsTrueArm ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE)) {
// Pass
} else {
C = dyn_cast<Constant>(Op);
}
if (C == nullptr)
return nullptr;

ConstOps.push_back(C);
}

return ConstantFoldInstOperands(&I, ConstOps, I.getModule()->getDataLayout());
}

Expand Down Expand Up @@ -1085,8 +1093,8 @@ Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
}

// Make sure that one of the select arms constant folds successfully.
Value *NewTV = constantFoldOperationIntoSelectOperand(Op, SI, TV);
Value *NewFV = constantFoldOperationIntoSelectOperand(Op, SI, FV);
Value *NewTV = constantFoldOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ true);
Value *NewFV = constantFoldOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ false);
if (!NewTV && !NewFV)
return nullptr;

Expand Down
8 changes: 4 additions & 4 deletions llvm/test/Transforms/InstCombine/binop-select.ll
Expand Up @@ -73,8 +73,8 @@ define i32 @test5(i1 %c, i32 %x, i32 %y) {
define i32 @test_sub_deduce_true(i32 %x, i32 %y) {
; CHECK-LABEL: @test_sub_deduce_true(
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 9
; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], i32 6, i32 [[Y:%.*]]
; CHECK-NEXT: [[SUB:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[X]], i32 [[COND]])
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[X]], i32 [[Y:%.*]])
; CHECK-NEXT: [[SUB:%.*]] = select i1 [[C]], i32 15, i32 [[TMP1]]
; CHECK-NEXT: ret i32 [[SUB]]
;
%c = icmp eq i32 %x, 9
Expand All @@ -99,8 +99,8 @@ define i32 @test_sub_deduce_true_no_const_fold(i32 %x, i32 %y) {
define i32 @test_sub_deduce_false(i32 %x, i32 %y) {
; CHECK-LABEL: @test_sub_deduce_false(
; CHECK-NEXT: [[C_NOT:%.*]] = icmp eq i32 [[X:%.*]], 9
; CHECK-NEXT: [[COND:%.*]] = select i1 [[C_NOT]], i32 7, i32 [[Y:%.*]]
; CHECK-NEXT: [[SUB:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[X]], i32 [[COND]])
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[X]], i32 [[Y:%.*]])
; CHECK-NEXT: [[SUB:%.*]] = select i1 [[C_NOT]], i32 16, i32 [[TMP1]]
; CHECK-NEXT: ret i32 [[SUB]]
;
%c = icmp ne i32 %x, 9
Expand Down

0 comments on commit 82f0827

Please sign in to comment.