Skip to content

Commit 5886f6e

Browse files
[InstCombine] Perform sext transformation for values with >1 users
1 parent 382b9e5 commit 5886f6e

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
@@ -415,6 +415,7 @@ class TypeEvaluationHelper {
415415
InstCombinerImpl &IC,
416416
Instruction *CxtI);
417417
[[nodiscard]] bool canEvaluateSExtdImpl(Value *V, Type *Ty);
418+
[[nodiscard]] bool canEvaluateSExtdPred(Value *V, Type *Ty);
418419

419420
/// A bookkeeping map to memorize an already made decision for a traversed
420421
/// 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

@@ -1682,16 +1685,18 @@ Instruction *InstCombinerImpl::transformSExtICmp(ICmpInst *Cmp,
16821685
///
16831686
bool TypeEvaluationHelper::canEvaluateSExtd(Value *V, Type *Ty) {
16841687
TypeEvaluationHelper TYH;
1685-
return TYH.canEvaluateSExtdImpl(V, Ty);
1688+
return TYH.canEvaluateSExtdImpl(V, Ty) && TYH.allPendingVisited();
16861689
}
16871690

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

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

1712-
//case Instruction::Shl: TODO
1713-
//case Instruction::LShr: TODO
1717+
// case Instruction::Shl: TODO
1718+
// case Instruction::LShr: TODO
17141719

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

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