Skip to content

Commit 86e604c

Browse files
committed
[RISCV] Add implementation of targetShrinkDemandedConstant to optimize AND immediates.
SimplifyDemandedBits can remove set bits from immediates from instructions like AND/OR/XOR. This can prevent them from being efficiently codegened on RISCV. This adds an initial version that tries to keep or form 12 bit sign extended immediates for AND operations to enable use of ANDI. If that doesn't work we'll try to create a 32 bit sign extended immediate to use LUI+ADDIW. More optimizations are possible for different size immediates or different operations. But this is a good starting point that already has test coverage. Reviewed By: frasercrmck Differential Revision: https://reviews.llvm.org/D94628
1 parent d0cb0d3 commit 86e604c

File tree

10 files changed

+196
-231
lines changed

10 files changed

+196
-231
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,71 @@ bool RISCVTargetLowering::isDesirableToCommuteWithShift(
19001900
return true;
19011901
}
19021902

1903+
bool RISCVTargetLowering::targetShrinkDemandedConstant(
1904+
SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts,
1905+
TargetLoweringOpt &TLO) const {
1906+
// Delay this optimization as late as possible.
1907+
if (!TLO.LegalOps)
1908+
return false;
1909+
1910+
EVT VT = Op.getValueType();
1911+
if (VT.isVector())
1912+
return false;
1913+
1914+
// Only handle AND for now.
1915+
if (Op.getOpcode() != ISD::AND)
1916+
return false;
1917+
1918+
ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
1919+
if (!C)
1920+
return false;
1921+
1922+
const APInt &Mask = C->getAPIntValue();
1923+
1924+
// Clear all non-demanded bits initially.
1925+
APInt ShrunkMask = Mask & DemandedBits;
1926+
1927+
// If the shrunk mask fits in sign extended 12 bits, let the target
1928+
// independent code apply it.
1929+
if (ShrunkMask.isSignedIntN(12))
1930+
return false;
1931+
1932+
// Try to make a smaller immediate by setting undemanded bits.
1933+
1934+
// We need to be able to make a negative number through a combination of mask
1935+
// and undemanded bits.
1936+
APInt ExpandedMask = Mask | ~DemandedBits;
1937+
if (!ExpandedMask.isNegative())
1938+
return false;
1939+
1940+
// What is the fewest number of bits we need to represent the negative number.
1941+
unsigned MinSignedBits = ExpandedMask.getMinSignedBits();
1942+
1943+
// Try to make a 12 bit negative immediate. If that fails try to make a 32
1944+
// bit negative immediate unless the shrunk immediate already fits in 32 bits.
1945+
APInt NewMask = ShrunkMask;
1946+
if (MinSignedBits <= 12)
1947+
NewMask.setBitsFrom(11);
1948+
else if (MinSignedBits <= 32 && !ShrunkMask.isSignedIntN(32))
1949+
NewMask.setBitsFrom(31);
1950+
else
1951+
return false;
1952+
1953+
// Sanity check that our new mask is a subset of the demanded mask.
1954+
assert(NewMask.isSubsetOf(ExpandedMask));
1955+
1956+
// If we aren't changing the mask, just return true to keep it and prevent
1957+
// the caller from optimizing.
1958+
if (NewMask == Mask)
1959+
return true;
1960+
1961+
// Replace the constant with the new mask.
1962+
SDLoc DL(Op);
1963+
SDValue NewC = TLO.DAG.getConstant(NewMask, DL, VT);
1964+
SDValue NewOp = TLO.DAG.getNode(ISD::AND, DL, VT, Op.getOperand(0), NewC);
1965+
return TLO.CombineTo(Op, NewOp);
1966+
}
1967+
19031968
void RISCVTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
19041969
KnownBits &Known,
19051970
const APInt &DemandedElts,

llvm/lib/Target/RISCV/RISCVISelLowering.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ class RISCVTargetLowering : public TargetLowering {
131131

132132
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
133133

134+
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits,
135+
const APInt &DemandedElts,
136+
TargetLoweringOpt &TLO) const override;
137+
134138
void computeKnownBitsForTargetNode(const SDValue Op,
135139
KnownBits &Known,
136140
const APInt &DemandedElts,

llvm/test/CodeGen/RISCV/copysign-casts.ll

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ define double @fold_promote_d_s(double %a, float %b) nounwind {
4242
; RV64I-NEXT: slli a2, a2, 63
4343
; RV64I-NEXT: addi a2, a2, -1
4444
; RV64I-NEXT: and a0, a0, a2
45-
; RV64I-NEXT: addi a2, zero, 1
46-
; RV64I-NEXT: slli a2, a2, 31
45+
; RV64I-NEXT: lui a2, 524288
4746
; RV64I-NEXT: and a1, a1, a2
4847
; RV64I-NEXT: slli a1, a1, 32
4948
; RV64I-NEXT: or a0, a0, a1
@@ -188,10 +187,7 @@ define float @fold_promote_f_h(float %a, half %b) nounwind {
188187
; RV64I-NEXT: lui a2, 524288
189188
; RV64I-NEXT: addiw a2, a2, -1
190189
; RV64I-NEXT: and a0, a0, a2
191-
; RV64I-NEXT: addi a2, zero, 1
192-
; RV64I-NEXT: slli a2, a2, 33
193-
; RV64I-NEXT: addi a2, a2, -1
194-
; RV64I-NEXT: slli a2, a2, 15
190+
; RV64I-NEXT: lui a2, 1048568
195191
; RV64I-NEXT: and a1, a1, a2
196192
; RV64I-NEXT: slli a1, a1, 16
197193
; RV64I-NEXT: or a0, a0, a1

llvm/test/CodeGen/RISCV/frame-info.ll

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,7 @@ define void @stack_alloc(i32 signext %size) {
8282
; RV64-NEXT: slli a0, a0, 32
8383
; RV64-NEXT: srli a0, a0, 32
8484
; RV64-NEXT: addi a0, a0, 15
85-
; RV64-NEXT: addi a1, zero, 1
86-
; RV64-NEXT: slli a1, a1, 33
87-
; RV64-NEXT: addi a1, a1, -16
88-
; RV64-NEXT: and a0, a0, a1
85+
; RV64-NEXT: andi a0, a0, -16
8986
; RV64-NEXT: sub a0, sp, a0
9087
; RV64-NEXT: mv sp, a0
9188
; RV64-NEXT: call callee_with_args@plt
@@ -129,10 +126,7 @@ define void @stack_alloc(i32 signext %size) {
129126
; RV64-WITHFP-NEXT: slli a0, a0, 32
130127
; RV64-WITHFP-NEXT: srli a0, a0, 32
131128
; RV64-WITHFP-NEXT: addi a0, a0, 15
132-
; RV64-WITHFP-NEXT: addi a1, zero, 1
133-
; RV64-WITHFP-NEXT: slli a1, a1, 33
134-
; RV64-WITHFP-NEXT: addi a1, a1, -16
135-
; RV64-WITHFP-NEXT: and a0, a0, a1
129+
; RV64-WITHFP-NEXT: andi a0, a0, -16
136130
; RV64-WITHFP-NEXT: sub a0, sp, a0
137131
; RV64-WITHFP-NEXT: mv sp, a0
138132
; RV64-WITHFP-NEXT: call callee_with_args@plt

llvm/test/CodeGen/RISCV/half-bitmanip-dagcombines.ll

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,7 @@ define half @fcopysign_fneg(half %a, half %b) nounwind {
122122
; RV64I-NEXT: lui a2, 524288
123123
; RV64I-NEXT: addiw a2, a2, -1
124124
; RV64I-NEXT: and a0, a0, a2
125-
; RV64I-NEXT: addi a2, zero, 1
126-
; RV64I-NEXT: slli a2, a2, 33
127-
; RV64I-NEXT: addi a2, a2, -1
128-
; RV64I-NEXT: slli a2, a2, 15
125+
; RV64I-NEXT: lui a2, 1048568
129126
; RV64I-NEXT: and a1, a1, a2
130127
; RV64I-NEXT: slli a1, a1, 16
131128
; RV64I-NEXT: or a0, a0, a1

0 commit comments

Comments
 (0)