Skip to content

Commit 39a7664

Browse files
authored
[RISCV] Select (add/or C, x) -> (add.uw C|0xffffffff00000000, x) (#143375)
Emits fewer instructions for certain constants.
1 parent c0f8145 commit 39a7664

File tree

6 files changed

+129
-64
lines changed

6 files changed

+129
-64
lines changed

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3307,6 +3307,50 @@ bool RISCVDAGToDAGISel::selectSHXADD_UWOp(SDValue N, unsigned ShAmt,
33073307
return false;
33083308
}
33093309

3310+
bool RISCVDAGToDAGISel::orIsAdd(const SDNode *N) const {
3311+
if (N->getFlags().hasDisjoint())
3312+
return true;
3313+
KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
3314+
KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
3315+
return KnownBits::haveNoCommonBitsSet(Known0, Known1);
3316+
}
3317+
3318+
bool RISCVDAGToDAGISel::selectImm64IfCheaper(int64_t Imm, int64_t OrigImm,
3319+
SDValue N, SDValue &Val) {
3320+
int OrigCost = RISCVMatInt::getIntMatCost(APInt(64, OrigImm), 64, *Subtarget,
3321+
/*CompressionCost=*/true);
3322+
int Cost = RISCVMatInt::getIntMatCost(APInt(64, Imm), 64, *Subtarget,
3323+
/*CompressionCost=*/true);
3324+
if (OrigCost <= Cost)
3325+
return false;
3326+
3327+
Val = selectImm(CurDAG, SDLoc(N), N->getSimpleValueType(0), Imm, *Subtarget);
3328+
return true;
3329+
}
3330+
3331+
bool RISCVDAGToDAGISel::selectZExtImm32(SDValue N, SDValue &Val) {
3332+
if (!isa<ConstantSDNode>(N))
3333+
return false;
3334+
int64_t Imm = cast<ConstantSDNode>(N)->getSExtValue();
3335+
if ((Imm >> 31) != 1)
3336+
return false;
3337+
3338+
for (const SDNode *U : N->users()) {
3339+
switch (U->getOpcode()) {
3340+
case ISD::ADD:
3341+
break;
3342+
case ISD::OR:
3343+
if (orIsAdd(U))
3344+
break;
3345+
return false;
3346+
default:
3347+
return false;
3348+
}
3349+
}
3350+
3351+
return selectImm64IfCheaper(0xffffffff00000000 | Imm, Imm, N, Val);
3352+
}
3353+
33103354
bool RISCVDAGToDAGISel::selectNegImm(SDValue N, SDValue &Val) {
33113355
if (!isa<ConstantSDNode>(N))
33123356
return false;
@@ -3330,15 +3374,7 @@ bool RISCVDAGToDAGISel::selectNegImm(SDValue N, SDValue &Val) {
33303374
}
33313375
}
33323376

3333-
int OrigImmCost = RISCVMatInt::getIntMatCost(APInt(64, Imm), 64, *Subtarget,
3334-
/*CompressionCost=*/true);
3335-
int NegImmCost = RISCVMatInt::getIntMatCost(APInt(64, -Imm), 64, *Subtarget,
3336-
/*CompressionCost=*/true);
3337-
if (OrigImmCost <= NegImmCost)
3338-
return false;
3339-
3340-
Val = selectImm(CurDAG, SDLoc(N), N->getSimpleValueType(0), -Imm, *Subtarget);
3341-
return true;
3377+
return selectImm64IfCheaper(-Imm, Imm, N, Val);
33423378
}
33433379

33443380
bool RISCVDAGToDAGISel::selectInvLogicImm(SDValue N, SDValue &Val) {
@@ -3373,19 +3409,15 @@ bool RISCVDAGToDAGISel::selectInvLogicImm(SDValue N, SDValue &Val) {
33733409
}
33743410
}
33753411

3376-
// For 64-bit constants, the instruction sequences get complex,
3377-
// so we select inverted only if it's cheaper.
3378-
if (!isInt<32>(Imm)) {
3379-
int OrigImmCost = RISCVMatInt::getIntMatCost(APInt(64, Imm), 64, *Subtarget,
3380-
/*CompressionCost=*/true);
3381-
int NegImmCost = RISCVMatInt::getIntMatCost(APInt(64, ~Imm), 64, *Subtarget,
3382-
/*CompressionCost=*/true);
3383-
if (OrigImmCost <= NegImmCost)
3384-
return false;
3412+
if (isInt<32>(Imm)) {
3413+
Val =
3414+
selectImm(CurDAG, SDLoc(N), N->getSimpleValueType(0), ~Imm, *Subtarget);
3415+
return true;
33853416
}
33863417

3387-
Val = selectImm(CurDAG, SDLoc(N), N->getSimpleValueType(0), ~Imm, *Subtarget);
3388-
return true;
3418+
// For 64-bit constants, the instruction sequences get complex,
3419+
// so we select inverted only if it's cheaper.
3420+
return selectImm64IfCheaper(~Imm, Imm, N, Val);
33893421
}
33903422

33913423
static bool vectorPseudoHasAllNBitUsers(SDNode *User, unsigned UserOpNo,

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,11 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
118118
return selectSHXADD_UWOp(N, ShAmt, Val);
119119
}
120120

121+
bool selectZExtImm32(SDValue N, SDValue &Val);
121122
bool selectNegImm(SDValue N, SDValue &Val);
122123
bool selectInvLogicImm(SDValue N, SDValue &Val);
123124

125+
bool orIsAdd(const SDNode *Node) const;
124126
bool hasAllNBitUsers(SDNode *Node, unsigned Bits,
125127
const unsigned Depth = 0) const;
126128
bool hasAllBUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 8); }
@@ -199,6 +201,8 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
199201
bool doPeepholeMergeVVMFold();
200202
bool doPeepholeNoRegPassThru();
201203
bool performCombineVMergeAndVOps(SDNode *N);
204+
bool selectImm64IfCheaper(int64_t Imm, int64_t OrigImm, SDValue N,
205+
SDValue &Val);
202206
};
203207

204208
class RISCVDAGToDAGISelLegacy : public SelectionDAGISelLegacy {

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,11 +1445,7 @@ def : PatGprUimmLog2XLen<sra, SRAI>;
14451445
// Select 'or' as ADDI if the immediate bits are known to be 0 in $rs1. This
14461446
// can improve compressibility.
14471447
def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
1448-
if (N->getFlags().hasDisjoint())
1449-
return true;
1450-
KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
1451-
KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
1452-
return KnownBits::haveNoCommonBitsSet(Known0, Known1);
1448+
return orIsAdd(N);
14531449
}]>;
14541450
def : PatGprSimm12<or_is_add, ADDI>;
14551451

llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -653,11 +653,7 @@ let HasOneUse = 1 in {
653653
node:$E),
654654
(riscv_or_vl node:$A, node:$B, node:$C,
655655
node:$D, node:$E), [{
656-
if (N->getFlags().hasDisjoint())
657-
return true;
658-
KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
659-
KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
660-
return KnownBits::haveNoCommonBitsSet(Known0, Known1);
656+
return orIsAdd(N);
661657
}]>;
662658
def riscv_sub_vl_oneuse : PatFrag<(ops node:$A, node:$B, node:$C, node:$D,
663659
node:$E),

llvm/lib/Target/RISCV/RISCVInstrInfoZb.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,9 +704,13 @@ def : CSImm12MulBy4Pat<SH2ADD>;
704704
def : CSImm12MulBy8Pat<SH3ADD>;
705705
} // Predicates = [HasStdExtZba]
706706

707+
def zExtImm32 : ComplexPattern<i64, 1, "selectZExtImm32", [], [], 0>;
708+
707709
multiclass ADD_UWPat<Instruction add_uw> {
708710
def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFFF), GPR:$rs2)),
709711
(add_uw GPR:$rs1, GPR:$rs2)>;
712+
def : Pat<(i64 (add_like zExtImm32:$rs1, GPR:$rs2)),
713+
(add_uw zExtImm32:$rs1, GPR:$rs2)>;
710714
def : Pat<(i64 (and GPR:$rs, 0xFFFFFFFF)), (add_uw GPR:$rs, (XLenVT X0))>;
711715
}
712716

llvm/test/CodeGen/RISCV/rv64zba.ll

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4260,10 +4260,11 @@ define i64 @add_u32simm32_zextw(i64 %x) nounwind {
42604260
;
42614261
; RV64XANDESPERF-LABEL: add_u32simm32_zextw:
42624262
; RV64XANDESPERF: # %bb.0: # %entry
4263+
; RV64XANDESPERF-NEXT: li a1, -2
4264+
; RV64XANDESPERF-NEXT: nds.lea.b.ze a0, a0, a1
42634265
; RV64XANDESPERF-NEXT: li a1, 1
42644266
; RV64XANDESPERF-NEXT: slli a1, a1, 32
42654267
; RV64XANDESPERF-NEXT: addi a1, a1, -2
4266-
; RV64XANDESPERF-NEXT: add a0, a0, a1
42674268
; RV64XANDESPERF-NEXT: addi a1, a1, 1
42684269
; RV64XANDESPERF-NEXT: and a0, a0, a1
42694270
; RV64XANDESPERF-NEXT: ret
@@ -4413,12 +4414,24 @@ define ptr @udiv1280_gep(ptr %p, i16 zeroext %i) {
44134414
}
44144415

44154416
define i64 @adduw_m1(i64 %x) {
4416-
; CHECK-LABEL: adduw_m1:
4417-
; CHECK: # %bb.0:
4418-
; CHECK-NEXT: li a1, -1
4419-
; CHECK-NEXT: srli a1, a1, 32
4420-
; CHECK-NEXT: add a0, a0, a1
4421-
; CHECK-NEXT: ret
4417+
; RV64I-LABEL: adduw_m1:
4418+
; RV64I: # %bb.0:
4419+
; RV64I-NEXT: li a1, -1
4420+
; RV64I-NEXT: srli a1, a1, 32
4421+
; RV64I-NEXT: add a0, a0, a1
4422+
; RV64I-NEXT: ret
4423+
;
4424+
; RV64ZBA-LABEL: adduw_m1:
4425+
; RV64ZBA: # %bb.0:
4426+
; RV64ZBA-NEXT: li a1, -1
4427+
; RV64ZBA-NEXT: add.uw a0, a1, a0
4428+
; RV64ZBA-NEXT: ret
4429+
;
4430+
; RV64XANDESPERF-LABEL: adduw_m1:
4431+
; RV64XANDESPERF: # %bb.0:
4432+
; RV64XANDESPERF-NEXT: li a1, -1
4433+
; RV64XANDESPERF-NEXT: nds.lea.b.ze a0, a0, a1
4434+
; RV64XANDESPERF-NEXT: ret
44224435
%a = add i64 %x, 4294967295
44234436
ret i64 %a
44244437
}
@@ -4435,28 +4448,37 @@ define i64 @adduw_m3(i64 %x) {
44354448
; RV64ZBA-LABEL: adduw_m3:
44364449
; RV64ZBA: # %bb.0:
44374450
; RV64ZBA-NEXT: li a1, -3
4438-
; RV64ZBA-NEXT: zext.w a1, a1
4439-
; RV64ZBA-NEXT: add a0, a0, a1
4451+
; RV64ZBA-NEXT: add.uw a0, a1, a0
44404452
; RV64ZBA-NEXT: ret
44414453
;
44424454
; RV64XANDESPERF-LABEL: adduw_m3:
44434455
; RV64XANDESPERF: # %bb.0:
4444-
; RV64XANDESPERF-NEXT: li a1, 1
4445-
; RV64XANDESPERF-NEXT: slli a1, a1, 32
4446-
; RV64XANDESPERF-NEXT: addi a1, a1, -3
4447-
; RV64XANDESPERF-NEXT: add a0, a0, a1
4456+
; RV64XANDESPERF-NEXT: li a1, -3
4457+
; RV64XANDESPERF-NEXT: nds.lea.b.ze a0, a0, a1
44484458
; RV64XANDESPERF-NEXT: ret
44494459
%a = add i64 %x, 4294967293
44504460
ret i64 %a
44514461
}
44524462

44534463
define i64 @adduw_3shl30(i64 %x) {
4454-
; CHECK-LABEL: adduw_3shl30:
4455-
; CHECK: # %bb.0:
4456-
; CHECK-NEXT: li a1, 3
4457-
; CHECK-NEXT: slli a1, a1, 30
4458-
; CHECK-NEXT: add a0, a0, a1
4459-
; CHECK-NEXT: ret
4464+
; RV64I-LABEL: adduw_3shl30:
4465+
; RV64I: # %bb.0:
4466+
; RV64I-NEXT: li a1, 3
4467+
; RV64I-NEXT: slli a1, a1, 30
4468+
; RV64I-NEXT: add a0, a0, a1
4469+
; RV64I-NEXT: ret
4470+
;
4471+
; RV64ZBA-LABEL: adduw_3shl30:
4472+
; RV64ZBA: # %bb.0:
4473+
; RV64ZBA-NEXT: lui a1, 786432
4474+
; RV64ZBA-NEXT: add.uw a0, a1, a0
4475+
; RV64ZBA-NEXT: ret
4476+
;
4477+
; RV64XANDESPERF-LABEL: adduw_3shl30:
4478+
; RV64XANDESPERF: # %bb.0:
4479+
; RV64XANDESPERF-NEXT: lui a1, 786432
4480+
; RV64XANDESPERF-NEXT: nds.lea.b.ze a0, a0, a1
4481+
; RV64XANDESPERF-NEXT: ret
44604482
%a = add i64 %x, 3221225472
44614483
ret i64 %a
44624484
}
@@ -4475,19 +4497,16 @@ define i64 @adduw_m3_multiuse(i64 %x, i64 %y) {
44754497
; RV64ZBA-LABEL: adduw_m3_multiuse:
44764498
; RV64ZBA: # %bb.0:
44774499
; RV64ZBA-NEXT: li a2, -3
4478-
; RV64ZBA-NEXT: zext.w a2, a2
4479-
; RV64ZBA-NEXT: add a0, a0, a2
4480-
; RV64ZBA-NEXT: add a1, a1, a2
4500+
; RV64ZBA-NEXT: add.uw a0, a2, a0
4501+
; RV64ZBA-NEXT: add.uw a1, a2, a1
44814502
; RV64ZBA-NEXT: or a0, a0, a1
44824503
; RV64ZBA-NEXT: ret
44834504
;
44844505
; RV64XANDESPERF-LABEL: adduw_m3_multiuse:
44854506
; RV64XANDESPERF: # %bb.0:
4486-
; RV64XANDESPERF-NEXT: li a2, 1
4487-
; RV64XANDESPERF-NEXT: slli a2, a2, 32
4488-
; RV64XANDESPERF-NEXT: addi a2, a2, -3
4489-
; RV64XANDESPERF-NEXT: add a0, a0, a2
4490-
; RV64XANDESPERF-NEXT: add a1, a1, a2
4507+
; RV64XANDESPERF-NEXT: li a2, -3
4508+
; RV64XANDESPERF-NEXT: nds.lea.b.ze a0, a0, a2
4509+
; RV64XANDESPERF-NEXT: nds.lea.b.ze a1, a1, a2
44914510
; RV64XANDESPERF-NEXT: or a0, a0, a1
44924511
; RV64XANDESPERF-NEXT: ret
44934512
%a = add i64 %x, 4294967293
@@ -4532,13 +4551,27 @@ define i64 @add_or_m3(i64 %x) {
45324551
}
45334552

45344553
define i64 @append_32ones(i64 %x) {
4535-
; CHECK-LABEL: append_32ones:
4536-
; CHECK: # %bb.0:
4537-
; CHECK-NEXT: slli a0, a0, 32
4538-
; CHECK-NEXT: li a1, -1
4539-
; CHECK-NEXT: srli a1, a1, 32
4540-
; CHECK-NEXT: or a0, a0, a1
4541-
; CHECK-NEXT: ret
4554+
; RV64I-LABEL: append_32ones:
4555+
; RV64I: # %bb.0:
4556+
; RV64I-NEXT: slli a0, a0, 32
4557+
; RV64I-NEXT: li a1, -1
4558+
; RV64I-NEXT: srli a1, a1, 32
4559+
; RV64I-NEXT: or a0, a0, a1
4560+
; RV64I-NEXT: ret
4561+
;
4562+
; RV64ZBA-LABEL: append_32ones:
4563+
; RV64ZBA: # %bb.0:
4564+
; RV64ZBA-NEXT: slli a0, a0, 32
4565+
; RV64ZBA-NEXT: li a1, -1
4566+
; RV64ZBA-NEXT: add.uw a0, a1, a0
4567+
; RV64ZBA-NEXT: ret
4568+
;
4569+
; RV64XANDESPERF-LABEL: append_32ones:
4570+
; RV64XANDESPERF: # %bb.0:
4571+
; RV64XANDESPERF-NEXT: slli a0, a0, 32
4572+
; RV64XANDESPERF-NEXT: li a1, -1
4573+
; RV64XANDESPERF-NEXT: nds.lea.b.ze a0, a0, a1
4574+
; RV64XANDESPERF-NEXT: ret
45424575
%s = shl i64 %x, 32
45434576
%o = or i64 %s, 4294967295
45444577
ret i64 %o

0 commit comments

Comments
 (0)