Skip to content

Commit e8715d2

Browse files
committed
[RISCV] Support constant hoisting of immediate store values
Previously getIntImmInstCost only calculated the cost of materialising the argument of a store if it was the address. This means ConstantHoisting's transformation wouldn't kick in for cases like storing two values that require multiple instructions to materialise but where one can be cheaply generated from the other (e.g. by an addition).
1 parent 4b0c078 commit e8715d2

File tree

5 files changed

+33
-15
lines changed

5 files changed

+33
-15
lines changed

llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ InstSeq generateTwoRegInstSeq(int64_t Val, const MCSubtargetInfo &STI,
499499
}
500500

501501
int getIntMatCost(const APInt &Val, unsigned Size, const MCSubtargetInfo &STI,
502-
bool CompressionCost) {
502+
bool CompressionCost, bool FreeZeroes) {
503503
bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
504504
bool HasRVC = CompressionCost && (STI.hasFeature(RISCV::FeatureStdExtC) ||
505505
STI.hasFeature(RISCV::FeatureStdExtZca));
@@ -510,10 +510,12 @@ int getIntMatCost(const APInt &Val, unsigned Size, const MCSubtargetInfo &STI,
510510
int Cost = 0;
511511
for (unsigned ShiftVal = 0; ShiftVal < Size; ShiftVal += PlatRegSize) {
512512
APInt Chunk = Val.ashr(ShiftVal).sextOrTrunc(PlatRegSize);
513+
if (FreeZeroes && Chunk == 0)
514+
continue;
513515
InstSeq MatSeq = generateInstSeq(Chunk.getSExtValue(), STI);
514516
Cost += getInstSeqCost(MatSeq, HasRVC);
515517
}
516-
return std::max(1, Cost);
518+
return std::max(FreeZeroes ? 0 : 1, Cost);
517519
}
518520

519521
OpndKind Inst::getOpndKind() const {

llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,13 @@ InstSeq generateTwoRegInstSeq(int64_t Val, const MCSubtargetInfo &STI,
7171
// If CompressionCost is true it will use a different cost calculation if RVC is
7272
// enabled. This should be used to compare two different sequences to determine
7373
// which is more compressible.
74+
//
75+
// If FreeZeroes is true, it will be assumed free to materialize any
76+
// XLen-sized chunks that are 0. This is appropriate to use in instances when
77+
// the zero register can be used, e.g. when estimating the cost of
78+
// materializing a value used by a particular operation.
7479
int getIntMatCost(const APInt &Val, unsigned Size, const MCSubtargetInfo &STI,
75-
bool CompressionCost = false);
80+
bool CompressionCost = false, bool FreeZeroes = false);
7681
} // namespace RISCVMatInt
7782
} // namespace llvm
7883
#endif

llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ InstructionCost RISCVTTIImpl::getIntImmCost(const APInt &Imm, Type *Ty,
120120

121121
// Otherwise, we check how many instructions it will take to materialise.
122122
const DataLayout &DL = getDataLayout();
123-
return RISCVMatInt::getIntMatCost(Imm, DL.getTypeSizeInBits(Ty), *getST());
123+
return RISCVMatInt::getIntMatCost(Imm, DL.getTypeSizeInBits(Ty), *getST(),
124+
/*CompressionCost=*/false,
125+
/*FreeZeroes=*/true);
124126
}
125127

126128
// Look for patterns of shift followed by AND that can be turned into a pair of
@@ -172,11 +174,22 @@ InstructionCost RISCVTTIImpl::getIntImmCostInst(unsigned Opcode, unsigned Idx,
172174
// split up large offsets in GEP into better parts than ConstantHoisting
173175
// can.
174176
return TTI::TCC_Free;
175-
case Instruction::Store:
176-
// If the address is a constant, use the materialization cost.
177-
if (Idx == 1)
177+
case Instruction::Store: {
178+
// Use the materialization cost regardless of if it's the address or the
179+
// value that is constant, except for if the store is misaligned and
180+
// misaligned accesses are not legal (experience shows constant hoisting
181+
// can sometimes be harmful in such cases).
182+
if (Idx == 1 || !Inst)
178183
return getIntImmCost(Imm, Ty, CostKind);
179-
return TTI::TCC_Free;
184+
185+
StoreInst *ST = cast<StoreInst>(Inst);
186+
if (!getTLI()->allowsMemoryAccessForAlignment(
187+
Ty->getContext(), DL, getTLI()->getValueType(DL, Ty),
188+
ST->getPointerAddressSpace(), ST->getAlign()))
189+
return TTI::TCC_Free;
190+
191+
return getIntImmCost(Imm, Ty, CostKind);
192+
}
180193
case Instruction::Load:
181194
// If the address is a constant, use the materialization cost.
182195
return getIntImmCost(Imm, Ty, CostKind);

llvm/test/CodeGen/RISCV/pr64935.ll

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
define i1 @f() {
55
; CHECK-LABEL: f:
66
; CHECK: # %bb.0:
7-
; CHECK-NEXT: lui a0, 524288
8-
; CHECK-NEXT: not a0, a0
9-
; CHECK-NEXT: sltiu a0, a0, 2
10-
; CHECK-NEXT: xori a0, a0, 1
7+
; CHECK-NEXT: li a0, 1
118
; CHECK-NEXT: ret
129
%B25 = shl i64 4294967296, -9223372036854775808
1310
%B13 = sub i64 -1, -9223372036854775808

llvm/test/Transforms/ConstantHoisting/RISCV/immediates.ll

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,12 @@ exit:
211211

212212
; Check that we use a common base for immediates needed by a store if the
213213
; constants require more than 1 instruction.
214-
; TODO: This doesn't trigger currently.
215214
define void @test20(ptr %p1, ptr %p2) {
216215
; CHECK-LABEL: test20
217-
; CHECK: store i32 15111111, ptr %p1
218-
; CHECK: store i32 15111112, ptr %p2
216+
; CHECK: %const = bitcast i32 15111111 to i32
217+
; CHECK: store i32 %const, ptr %p1, align 4
218+
; CHECK: %const_mat = add i32 %const, 1
219+
; CHECK: store i32 %const_mat, ptr %p2, align 4
219220
store i32 15111111, ptr %p1, align 4
220221
store i32 15111112, ptr %p2, align 4
221222
ret void

0 commit comments

Comments
 (0)