Skip to content

Commit c839ca0

Browse files
[ConstantHoisting] Add a TTI hook to prevent hoisting.
Code generation can sometimes simplify expensive operations when an operand is constant. An example of this is divides on AArch64 where they can be rewritten using a cheaper sequence of multiplies and subtracts. Doing this is often better than hoisting expensive constants which are likely to be hoisted by MachineLICM anyway.
1 parent f060d21 commit c839ca0

File tree

6 files changed

+55
-13
lines changed

6 files changed

+55
-13
lines changed

llvm/include/llvm/Analysis/TargetTransformInfo.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,16 @@ class TargetTransformInfo {
10021002
/// more beneficial constant hoisting is).
10031003
InstructionCost getIntImmCodeSizeCost(unsigned Opc, unsigned Idx,
10041004
const APInt &Imm, Type *Ty) const;
1005+
1006+
/// It can be advantageous to detach complex constants from their uses to make
1007+
/// their generation cheaper. This hook allows targets to report when such
1008+
/// transformations might negatively effect the code generation of the
1009+
/// underlying operation. The motivating example is divides whereby hoisting
1010+
/// constants prevents the code generator's ability to transform them into
1011+
/// combinations of simpler operations.
1012+
bool preferToKeepConstantsAttached(const Instruction &Inst,
1013+
const Function &Fn) const;
1014+
10051015
/// @}
10061016

10071017
/// \name Vector Target Information
@@ -1873,6 +1883,8 @@ class TargetTransformInfo::Concept {
18731883
virtual InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,
18741884
const APInt &Imm, Type *Ty,
18751885
TargetCostKind CostKind) = 0;
1886+
virtual bool preferToKeepConstantsAttached(const Instruction &Inst,
1887+
const Function &Fn) const = 0;
18761888
virtual unsigned getNumberOfRegisters(unsigned ClassID) const = 0;
18771889
virtual unsigned getRegisterClassForType(bool Vector,
18781890
Type *Ty = nullptr) const = 0;
@@ -2430,6 +2442,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
24302442
TargetCostKind CostKind) override {
24312443
return Impl.getIntImmCostIntrin(IID, Idx, Imm, Ty, CostKind);
24322444
}
2445+
bool preferToKeepConstantsAttached(const Instruction &Inst,
2446+
const Function &Fn) const override {
2447+
return Impl.preferToKeepConstantsAttached(Inst, Fn);
2448+
}
24332449
unsigned getNumberOfRegisters(unsigned ClassID) const override {
24342450
return Impl.getNumberOfRegisters(ClassID);
24352451
}

llvm/include/llvm/Analysis/TargetTransformInfoImpl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,11 @@ class TargetTransformInfoImplBase {
427427
return TTI::TCC_Free;
428428
}
429429

430+
bool preferToKeepConstantsAttached(const Instruction &Inst,
431+
const Function &Fn) const {
432+
return false;
433+
}
434+
430435
unsigned getNumberOfRegisters(unsigned ClassID) const { return 8; }
431436

432437
unsigned getRegisterClassForType(bool Vector, Type *Ty = nullptr) const {

llvm/include/llvm/CodeGen/BasicTTIImpl.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,25 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
545545
return TargetTransformInfo::TCC_Expensive;
546546
}
547547

548+
bool preferToKeepConstantsAttached(const Instruction &Inst,
549+
const Function &Fn) const {
550+
switch (Inst.getOpcode()) {
551+
default:
552+
break;
553+
case Instruction::SDiv:
554+
case Instruction::SRem:
555+
case Instruction::UDiv:
556+
case Instruction::URem: {
557+
if (!isa<ConstantInt>(Inst.getOperand(1)))
558+
return false;
559+
EVT VT = getTLI()->getValueType(DL, Inst.getType());
560+
return !getTLI()->isIntDivCheap(VT, Fn.getAttributes());
561+
}
562+
};
563+
564+
return false;
565+
}
566+
548567
unsigned getInliningThresholdMultiplier() const { return 1; }
549568
unsigned adjustInliningThreshold(const CallBase *CB) { return 0; }
550569
unsigned getCallerAllocaCost(const CallBase *CB, const AllocaInst *AI) const {

llvm/lib/Analysis/TargetTransformInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,11 @@ TargetTransformInfo::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,
682682
return Cost;
683683
}
684684

685+
bool TargetTransformInfo::preferToKeepConstantsAttached(
686+
const Instruction &Inst, const Function &Fn) const {
687+
return TTIImpl->preferToKeepConstantsAttached(Inst, Fn);
688+
}
689+
685690
unsigned TargetTransformInfo::getNumberOfRegisters(unsigned ClassID) const {
686691
return TTIImpl->getNumberOfRegisters(ClassID);
687692
}

llvm/lib/Transforms/Scalar/ConstantHoisting.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,8 @@ void ConstantHoistingPass::collectConstantCandidates(Function &Fn) {
523523
if (!DT->isReachableFromEntry(&BB))
524524
continue;
525525
for (Instruction &Inst : BB)
526-
collectConstantCandidates(ConstCandMap, &Inst);
526+
if (!TTI->preferToKeepConstantsAttached(Inst, Fn))
527+
collectConstantCandidates(ConstCandMap, &Inst);
527528
}
528529
}
529530

llvm/test/Transforms/ConstantHoisting/AArch64/large-immediate.ll

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,8 @@ define i512 @test3(i512 %a) {
4444
define i64 @sdiv(i64 %a) {
4545
; CHECK-LABEL: define i64 @sdiv(
4646
; CHECK-SAME: i64 [[A:%.*]]) {
47-
; CHECK-NEXT: [[CONST:%.*]] = bitcast i64 4294967087 to i64
48-
; CHECK-NEXT: [[TMP1:%.*]] = sdiv i64 [[A]], [[CONST]]
49-
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], [[CONST]]
47+
; CHECK-NEXT: [[TMP1:%.*]] = sdiv i64 [[A]], 4294967087
48+
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 4294967087
5049
; CHECK-NEXT: ret i64 [[TMP2]]
5150
;
5251
%1 = sdiv i64 %a, 4294967087
@@ -58,9 +57,8 @@ define i64 @sdiv(i64 %a) {
5857
define i64 @srem(i64 %a) {
5958
; CHECK-LABEL: define i64 @srem(
6059
; CHECK-SAME: i64 [[A:%.*]]) {
61-
; CHECK-NEXT: [[CONST:%.*]] = bitcast i64 4294967087 to i64
62-
; CHECK-NEXT: [[TMP1:%.*]] = srem i64 [[A]], [[CONST]]
63-
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], [[CONST]]
60+
; CHECK-NEXT: [[TMP1:%.*]] = srem i64 [[A]], 4294967087
61+
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 4294967087
6462
; CHECK-NEXT: ret i64 [[TMP2]]
6563
;
6664
%1 = srem i64 %a, 4294967087
@@ -72,9 +70,8 @@ define i64 @srem(i64 %a) {
7270
define i64 @udiv(i64 %a) {
7371
; CHECK-LABEL: define i64 @udiv(
7472
; CHECK-SAME: i64 [[A:%.*]]) {
75-
; CHECK-NEXT: [[CONST:%.*]] = bitcast i64 4294967087 to i64
76-
; CHECK-NEXT: [[TMP1:%.*]] = udiv i64 [[A]], [[CONST]]
77-
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], [[CONST]]
73+
; CHECK-NEXT: [[TMP1:%.*]] = udiv i64 [[A]], 4294967087
74+
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 4294967087
7875
; CHECK-NEXT: ret i64 [[TMP2]]
7976
;
8077
%1 = udiv i64 %a, 4294967087
@@ -86,9 +83,8 @@ define i64 @udiv(i64 %a) {
8683
define i64 @urem(i64 %a) {
8784
; CHECK-LABEL: define i64 @urem(
8885
; CHECK-SAME: i64 [[A:%.*]]) {
89-
; CHECK-NEXT: [[CONST:%.*]] = bitcast i64 4294967087 to i64
90-
; CHECK-NEXT: [[TMP1:%.*]] = urem i64 [[A]], [[CONST]]
91-
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], [[CONST]]
86+
; CHECK-NEXT: [[TMP1:%.*]] = urem i64 [[A]], 4294967087
87+
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 4294967087
9288
; CHECK-NEXT: ret i64 [[TMP2]]
9389
;
9490
%1 = urem i64 %a, 4294967087

0 commit comments

Comments
 (0)