Skip to content

Commit bc04f35

Browse files
[InstCombine] Perform sext transformation for values with >1 users
1 parent 5e11fe4 commit bc04f35

File tree

3 files changed

+34
-33
lines changed

3 files changed

+34
-33
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ class TypeEvaluationHelper {
416416
InstCombinerImpl &IC,
417417
Instruction *CxtI);
418418
[[nodiscard]] bool canEvaluateSExtdImpl(Value *V, Type *Ty);
419+
[[nodiscard]] bool canEvaluateSExtdPred(Value *V, Type *Ty);
419420

420421
/// A bookkeeping map to memorize an already made decision for a traversed
421422
/// value.
@@ -1332,6 +1333,8 @@ bool TypeEvaluationHelper::canEvaluateZExtdImpl(Value *V, Type *Ty,
13321333
BitsToClear = 0;
13331334
if (canAlwaysEvaluateInType(V, Ty))
13341335
return true;
1336+
// We stick to the one-user limit for the ZExt transform due to the fact
1337+
// that this predicate returns two values: predicate result and BitsToClear.
13351338
if (canNotEvaluateInType(V, Ty))
13361339
return false;
13371340

@@ -1681,16 +1684,18 @@ Instruction *InstCombinerImpl::transformSExtICmp(ICmpInst *Cmp,
16811684
///
16821685
bool TypeEvaluationHelper::canEvaluateSExtd(Value *V, Type *Ty) {
16831686
TypeEvaluationHelper TYH;
1684-
return TYH.canEvaluateSExtdImpl(V, Ty);
1687+
return TYH.canEvaluateSExtdImpl(V, Ty) && TYH.allPendingVisited();
16851688
}
16861689

16871690
bool TypeEvaluationHelper::canEvaluateSExtdImpl(Value *V, Type *Ty) {
1691+
return canEvaluate(V, Ty, [this](Value *V, Type *Ty) {
1692+
return canEvaluateSExtdPred(V, Ty);
1693+
});
1694+
}
1695+
1696+
bool TypeEvaluationHelper::canEvaluateSExtdPred(Value *V, Type *Ty) {
16881697
assert(V->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits() &&
16891698
"Can't sign extend type to a smaller type");
1690-
if (canAlwaysEvaluateInType(V, Ty))
1691-
return true;
1692-
if (canNotEvaluateInType(V, Ty))
1693-
return false;
16941699

16951700
auto *I = cast<Instruction>(V);
16961701
switch (I->getOpcode()) {
@@ -1708,20 +1713,21 @@ bool TypeEvaluationHelper::canEvaluateSExtdImpl(Value *V, Type *Ty) {
17081713
return canEvaluateSExtdImpl(I->getOperand(0), Ty) &&
17091714
canEvaluateSExtdImpl(I->getOperand(1), Ty);
17101715

1711-
//case Instruction::Shl: TODO
1712-
//case Instruction::LShr: TODO
1716+
// case Instruction::Shl: TODO
1717+
// case Instruction::LShr: TODO
17131718

17141719
case Instruction::Select:
17151720
return canEvaluateSExtdImpl(I->getOperand(1), Ty) &&
17161721
canEvaluateSExtdImpl(I->getOperand(2), Ty);
17171722

17181723
case Instruction::PHI: {
17191724
// We can change a phi if we can change all operands. Note that we never
1720-
// get into trouble with cyclic PHIs here because we only consider
1721-
// instructions with a single use.
1725+
// get into trouble with cyclic PHIs here because canEvaluate handles use
1726+
// chain loops.
17221727
PHINode *PN = cast<PHINode>(I);
17231728
for (Value *IncValue : PN->incoming_values())
1724-
if (!canEvaluateSExtdImpl(IncValue, Ty)) return false;
1729+
if (!canEvaluateSExtdImpl(IncValue, Ty))
1730+
return false;
17251731
return true;
17261732
}
17271733
default:

llvm/test/Transforms/InstCombine/cast-mul-select.ll

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -139,25 +139,21 @@ define i32 @eval_zext_multi_use_in_one_inst(i32 %x) {
139139

140140
define i32 @eval_sext_multi_use_in_one_inst(i32 %x) {
141141
; CHECK-LABEL: @eval_sext_multi_use_in_one_inst(
142-
; CHECK-NEXT: [[T:%.*]] = trunc i32 [[X:%.*]] to i16
143-
; CHECK-NEXT: [[A:%.*]] = and i16 [[T]], 14
144-
; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i16 [[A]], [[A]]
145-
; CHECK-NEXT: [[O:%.*]] = or disjoint i16 [[M]], -32768
146-
; CHECK-NEXT: [[R:%.*]] = sext i16 [[O]] to i32
142+
; CHECK-NEXT: [[A:%.*]] = and i32 [[X:%.*]], 14
143+
; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[A]], [[A]]
144+
; CHECK-NEXT: [[R:%.*]] = or disjoint i32 [[M]], -32768
147145
; CHECK-NEXT: ret i32 [[R]]
148146
;
149147
; DBGINFO-LABEL: @eval_sext_multi_use_in_one_inst(
150-
; DBGINFO-NEXT: [[T:%.*]] = trunc i32 [[X:%.*]] to i16, !dbg [[DBG81:![0-9]+]]
151-
; DBGINFO-NEXT: #dbg_value(i16 [[T]], [[META76:![0-9]+]], !DIExpression(), [[DBG81]])
152-
; DBGINFO-NEXT: [[A:%.*]] = and i16 [[T]], 14, !dbg [[DBG82:![0-9]+]]
153-
; DBGINFO-NEXT: #dbg_value(i16 [[A]], [[META77:![0-9]+]], !DIExpression(), [[DBG82]])
154-
; DBGINFO-NEXT: [[M:%.*]] = mul nuw nsw i16 [[A]], [[A]], !dbg [[DBG83:![0-9]+]]
155-
; DBGINFO-NEXT: #dbg_value(i16 [[M]], [[META78:![0-9]+]], !DIExpression(), [[DBG83]])
156-
; DBGINFO-NEXT: [[O:%.*]] = or disjoint i16 [[M]], -32768, !dbg [[DBG84:![0-9]+]]
157-
; DBGINFO-NEXT: #dbg_value(i16 [[O]], [[META79:![0-9]+]], !DIExpression(), [[DBG84]])
158-
; DBGINFO-NEXT: [[R:%.*]] = sext i16 [[O]] to i32, !dbg [[DBG85:![0-9]+]]
159-
; DBGINFO-NEXT: #dbg_value(i32 [[R]], [[META80:![0-9]+]], !DIExpression(), [[DBG85]])
160-
; DBGINFO-NEXT: ret i32 [[R]], !dbg [[DBG86:![0-9]+]]
148+
; DBGINFO-NEXT: #dbg_value(i32 [[X:%.*]], [[META76:![0-9]+]], !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_stack_value), [[META81:![0-9]+]])
149+
; DBGINFO-NEXT: [[A:%.*]] = and i32 [[X]], 14, !dbg [[DBG82:![0-9]+]]
150+
; DBGINFO-NEXT: #dbg_value(i32 [[X]], [[META77:![0-9]+]], !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_constu, 14, DW_OP_and, DW_OP_stack_value), [[DBG82]])
151+
; DBGINFO-NEXT: [[M:%.*]] = mul nuw nsw i32 [[A]], [[A]], !dbg [[DBG83:![0-9]+]]
152+
; DBGINFO-NEXT: #dbg_value(!DIArgList(i32 [[X]], i32 [[X]]), [[META78:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_constu, 14, DW_OP_and, DW_OP_LLVM_arg, 1, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_constu, 14, DW_OP_and, DW_OP_mul, DW_OP_stack_value), [[DBG83]])
153+
; DBGINFO-NEXT: [[O:%.*]] = or disjoint i32 [[M]], -32768, !dbg [[DBG84:![0-9]+]]
154+
; DBGINFO-NEXT: #dbg_value(!DIArgList(i32 [[X]], i32 [[X]]), [[META79:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_constu, 14, DW_OP_and, DW_OP_LLVM_arg, 1, DW_OP_LLVM_convert, 32, DW_ATE_unsigned, DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_constu, 14, DW_OP_and, DW_OP_mul, DW_OP_constu, 18446744073709518848, DW_OP_or, DW_OP_stack_value), [[DBG84]])
155+
; DBGINFO-NEXT: #dbg_value(i32 [[O]], [[META80:![0-9]+]], !DIExpression(), [[META85:![0-9]+]])
156+
; DBGINFO-NEXT: ret i32 [[O]], !dbg [[DBG86:![0-9]+]]
161157
;
162158
%t = trunc i32 %x to i16
163159
%a = and i16 %t, 14

llvm/test/Transforms/InstCombine/cast.ll

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2312,13 +2312,12 @@ exit:
23122312

23132313
define i32 @test99(i32 %x, i32 %y) {
23142314
; ALL-LABEL: @test99(
2315-
; ALL-NEXT: [[TX:%.*]] = trunc i32 [[X:%.*]] to i16
2316-
; ALL-NEXT: [[TY:%.*]] = trunc i32 [[Y:%.*]] to i16
2317-
; ALL-NEXT: [[A:%.*]] = add i16 [[TX]], [[TY]]
2318-
; ALL-NEXT: [[B:%.*]] = add i16 [[A]], 5
2319-
; ALL-NEXT: [[C:%.*]] = mul i16 [[A]], 3
2320-
; ALL-NEXT: [[D:%.*]] = or i16 [[B]], [[C]]
2321-
; ALL-NEXT: [[S:%.*]] = sext i16 [[D]] to i32
2315+
; ALL-NEXT: [[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
2316+
; ALL-NEXT: [[B:%.*]] = add i32 [[A]], 5
2317+
; ALL-NEXT: [[C:%.*]] = mul i32 [[A]], 3
2318+
; ALL-NEXT: [[D:%.*]] = or i32 [[B]], [[C]]
2319+
; ALL-NEXT: [[SEXT:%.*]] = shl i32 [[D]], 16
2320+
; ALL-NEXT: [[S:%.*]] = ashr exact i32 [[SEXT]], 16
23222321
; ALL-NEXT: ret i32 [[S]]
23232322
;
23242323
%tx = trunc i32 %x to i16

0 commit comments

Comments
 (0)