Skip to content

Commit 5559d54

Browse files
[InstCombine] Perform sext transformation for values with >1 users
1 parent 3a48c3e commit 5559d54

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.
@@ -1333,6 +1334,8 @@ bool TypeEvaluationHelper::canEvaluateZExtdImpl(Value *V, Type *Ty,
13331334
BitsToClear = 0;
13341335
if (canAlwaysEvaluateInType(V, Ty))
13351336
return true;
1337+
// We stick to the one-user limit for the ZExt transform due to the fact
1338+
// that this predicate returns two values: predicate result and BitsToClear.
13361339
if (canNotEvaluateInType(V, Ty))
13371340
return false;
13381341

@@ -1683,16 +1686,18 @@ Instruction *InstCombinerImpl::transformSExtICmp(ICmpInst *Cmp,
16831686
///
16841687
bool TypeEvaluationHelper::canEvaluateSExtd(Value *V, Type *Ty) {
16851688
TypeEvaluationHelper TYH;
1686-
return TYH.canEvaluateSExtdImpl(V, Ty);
1689+
return TYH.canEvaluateSExtdImpl(V, Ty) && TYH.allPendingVisited();
16871690
}
16881691

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

16971702
auto *I = cast<Instruction>(V);
16981703
switch (I->getOpcode()) {
@@ -1710,20 +1715,21 @@ bool TypeEvaluationHelper::canEvaluateSExtdImpl(Value *V, Type *Ty) {
17101715
return canEvaluateSExtdImpl(I->getOperand(0), Ty) &&
17111716
canEvaluateSExtdImpl(I->getOperand(1), Ty);
17121717

1713-
//case Instruction::Shl: TODO
1714-
//case Instruction::LShr: TODO
1718+
// case Instruction::Shl: TODO
1719+
// case Instruction::LShr: TODO
17151720

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

17201725
case Instruction::PHI: {
17211726
// We can change a phi if we can change all operands. Note that we never
1722-
// get into trouble with cyclic PHIs here because we only consider
1723-
// instructions with a single use.
1727+
// get into trouble with cyclic PHIs here because canEvaluate handles use
1728+
// chain loops.
17241729
PHINode *PN = cast<PHINode>(I);
17251730
for (Value *IncValue : PN->incoming_values())
1726-
if (!canEvaluateSExtdImpl(IncValue, Ty)) return false;
1731+
if (!canEvaluateSExtdImpl(IncValue, Ty))
1732+
return false;
17271733
return true;
17281734
}
17291735
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)