Skip to content

Commit 43a3599

Browse files
committed
SILOptimizer: Teach constant folding about add, sub, mul variants without overflow checks
1 parent 1b72106 commit 43a3599

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

lib/SILOptimizer/Utils/ConstantFolding.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,31 @@ static SILValue constantFoldBinary(BuiltinInst *BI,
588588
// Are there valid uses for these in stdlib?
589589
case BuiltinValueKind::Add:
590590
case BuiltinValueKind::Mul:
591-
case BuiltinValueKind::Sub:
592-
return nullptr;
591+
case BuiltinValueKind::Sub: {
592+
OperandValueArrayRef Args = BI->getArguments();
593+
auto *LHS = dyn_cast<IntegerLiteralInst>(Args[0]);
594+
auto *RHS = dyn_cast<IntegerLiteralInst>(Args[1]);
595+
if (!RHS || !LHS)
596+
return nullptr;
597+
APInt LHSI = LHS->getValue();
598+
APInt RHSI = RHS->getValue();
599+
600+
switch (ID) {
601+
default: llvm_unreachable("Not all cases are covered!");
602+
case BuiltinValueKind::Add:
603+
LHSI += RHSI;
604+
break;
605+
case BuiltinValueKind::Mul:
606+
LHSI *= RHSI;
607+
break;
608+
case BuiltinValueKind::Sub:
609+
LHSI -= RHSI;
610+
break;
611+
}
612+
613+
SILBuilderWithScope B(BI);
614+
return B.createIntegerLiteral(BI->getLoc(), BI->getType(), LHSI);
615+
}
593616

594617
case BuiltinValueKind::And:
595618
case BuiltinValueKind::AShr:

test/SILOptimizer/constant_propagation.sil

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,25 @@ bb0:
102102
// CHECK-NEXT: return [[RES]] : $Builtin.Int64
103103
}
104104

105+
// Compute an expression using a chain of arithmetic with non-overflowing instructions: 2 * (2 + 3) - 3
106+
sil @fold_arithmetic_without_overflow : $@convention(thin) () -> Builtin.Int64 {
107+
bb0:
108+
%0 = integer_literal $Builtin.Int64, 2
109+
%110 = integer_literal $Builtin.Int64, 3
110+
%19 = builtin "add_Int64"(%0 : $Builtin.Int64, %110 : $Builtin.Int64) : $Builtin.Int64
111+
%21 = builtin "mul_Int64"(%0 : $Builtin.Int64, %19 : $Builtin.Int64) : $Builtin.Int64
112+
%23 = builtin "sub_Int64"(%21 : $Builtin.Int64, %110 : $Builtin.Int64) : $Builtin.Int64
113+
return %23 : $Builtin.Int64
114+
115+
// CHECK-LABEL: sil @fold_arithmetic_without_overflow
116+
// CHECK-NOT: integer_literal $Builtin.Int64, 2
117+
// CHECK-NOT: integer_literal $Builtin.Int64, 3
118+
// CHECK-NOT: integer_literal $Builtin.Int64, 0
119+
// CHECK-NOT: builtin
120+
// CHECK: [[RES:%.*]] = integer_literal $Builtin.Int64, 7
121+
// CHECK-NEXT: return [[RES]] : $Builtin.Int64
122+
}
123+
105124
// Fold casts. (This test assumes that DCE does not run, otherwise the unreachable blocks will get removed.)
106125
sil @fold_trunc : $@convention(thin) () -> Builtin.Int64 {
107126
bb0:

0 commit comments

Comments
 (0)