Skip to content

Commit 71b02ab

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 846c4a9 commit 71b02ab

File tree

7 files changed

+62
-13
lines changed

7 files changed

+62
-13
lines changed

llvm/include/llvm/Analysis/TargetTransformInfo.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,18 @@ class TargetTransformInfo {
986986
/// more beneficial constant hoisting is).
987987
InstructionCost getIntImmCodeSizeCost(unsigned Opc, unsigned Idx,
988988
const APInt &Imm, Type *Ty) const;
989+
990+
/// Returns false if the target prefers to keep an instruction's constant
991+
/// operands attached. It is not required for this function to perform
992+
/// detailed constant analysis and in fact returning true does not imply
993+
/// the instruction has any constant operands. This hook exists soley to
994+
/// disable constant hoisting for reasons beyond the cost of generating a
995+
/// constant. The motivating example is divides whereby hoisting constants
996+
/// prevents the code generator's ability to transform them into combinations
997+
/// of simpler operations.
998+
bool isCandidateForConstantHoisting(const Instruction &Inst,
999+
const Function &Fn) const;
1000+
9891001
/// @}
9901002

9911003
/// \name Vector Target Information
@@ -1847,6 +1859,8 @@ class TargetTransformInfo::Concept {
18471859
virtual InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,
18481860
const APInt &Imm, Type *Ty,
18491861
TargetCostKind CostKind) = 0;
1862+
virtual bool isCandidateForConstantHoisting(const Instruction &Inst,
1863+
const Function &Fn) const = 0;
18501864
virtual unsigned getNumberOfRegisters(unsigned ClassID) const = 0;
18511865
virtual unsigned getRegisterClassForType(bool Vector,
18521866
Type *Ty = nullptr) const = 0;
@@ -2399,6 +2413,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
23992413
TargetCostKind CostKind) override {
24002414
return Impl.getIntImmCostIntrin(IID, Idx, Imm, Ty, CostKind);
24012415
}
2416+
bool isCandidateForConstantHoisting(const Instruction &Inst,
2417+
const Function &Fn) const override {
2418+
return Impl.isCandidateForConstantHoisting(Inst, Fn);
2419+
}
24022420
unsigned getNumberOfRegisters(unsigned ClassID) const override {
24032421
return Impl.getNumberOfRegisters(ClassID);
24042422
}

llvm/include/llvm/Analysis/TargetTransformInfoImpl.h

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

428+
bool isCandidateForConstantHoisting(const Instruction &Inst,
429+
const Function &Fn) const {
430+
return true;
431+
}
432+
428433
unsigned getNumberOfRegisters(unsigned ClassID) const { return 8; }
429434

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

llvm/lib/Analysis/TargetTransformInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,11 @@ TargetTransformInfo::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,
678678
return Cost;
679679
}
680680

681+
bool TargetTransformInfo::isCandidateForConstantHoisting(
682+
const Instruction &Inst, const Function &Fn) const {
683+
return TTIImpl->isCandidateForConstantHoisting(Inst, Fn);
684+
}
685+
681686
unsigned TargetTransformInfo::getNumberOfRegisters(unsigned ClassID) const {
682687
return TTIImpl->getNumberOfRegisters(ClassID);
683688
}

llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,25 @@ AArch64TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,
382382
return AArch64TTIImpl::getIntImmCost(Imm, Ty, CostKind);
383383
}
384384

385+
bool AArch64TTIImpl::isCandidateForConstantHoisting(const Instruction &Inst,
386+
const Function &Fn) const {
387+
switch (Inst.getOpcode()) {
388+
default:
389+
break;
390+
case Instruction::SDiv:
391+
case Instruction::SRem:
392+
case Instruction::UDiv:
393+
case Instruction::URem: {
394+
if (!isa<ConstantInt>(Inst.getOperand(1)))
395+
return true;
396+
EVT VT = TLI->getValueType(DL, Inst.getType());
397+
return TLI->isIntDivCheap(VT, Fn.getAttributes());
398+
}
399+
};
400+
401+
return true;
402+
}
403+
385404
TargetTransformInfo::PopcntSupportKind
386405
AArch64TTIImpl::getPopcntSupport(unsigned TyWidth) {
387406
assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2");

llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ class AArch64TTIImpl : public BasicTTIImplBase<AArch64TTIImpl> {
9191
InstructionCost getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx,
9292
const APInt &Imm, Type *Ty,
9393
TTI::TargetCostKind CostKind);
94+
95+
bool isCandidateForConstantHoisting(const Instruction &Inst,
96+
const Function &Fn) const;
97+
9498
TTI::PopcntSupportKind getPopcntSupport(unsigned TyWidth);
9599

96100
/// @}

llvm/lib/Transforms/Scalar/ConstantHoisting.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,9 @@ void ConstantHoistingPass::collectConstantCandidates(Function &Fn) {
523523
if (!DT->isReachableFromEntry(&BB))
524524
continue;
525525
for (Instruction &Inst : BB)
526-
collectConstantCandidates(ConstCandMap, &Inst);
526+
// Skip instructions the target prefers constants remain attached.
527+
if (TTI->isCandidateForConstantHoisting(Inst, Fn))
528+
collectConstantCandidates(ConstCandMap, &Inst);
527529
}
528530
}
529531

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)