Skip to content

Commit 784a2cd

Browse files
authored
[RISCV] Rewrite RISCVCodeGenPrepare using zext nneg [nfc-ish] (#70739)
This stacks on #70725. Once we have lowering for zext nneg, we can rewrite all of the existing RISCVCodeGenPrepare login in terms of zext nneg instead of sext. The change isn't NFC from the perspective of the individual pass, but should be from the perspective of codegen as a whole. As noted in the TODO, one piece can be moved to instcombine, but I'll leave that to a separate commit.
1 parent 8a786be commit 784a2cd

File tree

2 files changed

+24
-30
lines changed

2 files changed

+24
-30
lines changed

llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -62,38 +62,32 @@ bool RISCVCodeGenPrepare::visitZExtInst(ZExtInst &ZExt) {
6262
if (!ST->is64Bit())
6363
return false;
6464

65+
if (ZExt.hasNonNeg())
66+
return false;
67+
6568
Value *Src = ZExt.getOperand(0);
6669

6770
// We only care about ZExt from i32 to i64.
6871
if (!ZExt.getType()->isIntegerTy(64) || !Src->getType()->isIntegerTy(32))
6972
return false;
7073

71-
// Look for an opportunity to replace (i64 (zext (i32 X))) with a sext if we
72-
// can determine that the sign bit of X is zero via a dominating condition.
73-
// This often occurs with widened induction variables.
74+
// Look for an opportunity to infer nneg on a zext if we can determine that
75+
// the sign bit of X is zero via a dominating condition. This often occurs
76+
// with widened induction variables.
7477
if (isImpliedByDomCondition(ICmpInst::ICMP_SGE, Src,
7578
Constant::getNullValue(Src->getType()), &ZExt,
7679
*DL).value_or(false)) {
77-
auto *SExt = new SExtInst(Src, ZExt.getType(), "", &ZExt);
78-
SExt->takeName(&ZExt);
79-
SExt->setDebugLoc(ZExt.getDebugLoc());
80-
81-
ZExt.replaceAllUsesWith(SExt);
82-
ZExt.eraseFromParent();
80+
ZExt.setNonNeg(true);
8381
++NumZExtToSExt;
8482
return true;
8583
}
8684

87-
// Convert (zext (abs(i32 X, i1 1))) -> (sext (abs(i32 X, i1 1))). If abs of
85+
// Convert (zext (abs(i32 X, i1 1))) -> (zext nneg (abs(i32 X, i1 1))). If abs of
8886
// INT_MIN is poison, the sign bit is zero.
87+
// TODO: Move this to instcombine now that we have zext nneg in IR.
8988
using namespace PatternMatch;
9089
if (match(Src, m_Intrinsic<Intrinsic::abs>(m_Value(), m_One()))) {
91-
auto *SExt = new SExtInst(Src, ZExt.getType(), "", &ZExt);
92-
SExt->takeName(&ZExt);
93-
SExt->setDebugLoc(ZExt.getDebugLoc());
94-
95-
ZExt.replaceAllUsesWith(SExt);
96-
ZExt.eraseFromParent();
90+
ZExt.setNonNeg(true);
9791
++NumZExtToSExt;
9892
return true;
9993
}
@@ -102,19 +96,26 @@ bool RISCVCodeGenPrepare::visitZExtInst(ZExtInst &ZExt) {
10296
}
10397

10498
// Try to optimize (i64 (and (zext/sext (i32 X), C1))) if C1 has bit 31 set,
105-
// but bits 63:32 are zero. If we can prove that bit 31 of X is 0, we can fill
106-
// the upper 32 bits with ones. A separate transform will turn (zext X) into
107-
// (sext X) for the same condition.
99+
// but bits 63:32 are zero. If we know that bit 31 of X is 0, we can fill
100+
// the upper 32 bits with ones.
108101
bool RISCVCodeGenPrepare::visitAnd(BinaryOperator &BO) {
109102
if (!ST->is64Bit())
110103
return false;
111104

112105
if (!BO.getType()->isIntegerTy(64))
113106
return false;
114107

115-
// Left hand side should be sext or zext.
108+
auto canBeSignExtend = [](Instruction *I) {
109+
if (isa<SExtInst>(I))
110+
return true;
111+
if (isa<ZExtInst>(I))
112+
return I->hasNonNeg();
113+
return false;
114+
};
115+
116+
// Left hand side should be a sext or zext nneg.
116117
Instruction *LHS = dyn_cast<Instruction>(BO.getOperand(0));
117-
if (!LHS || (!isa<SExtInst>(LHS) && !isa<ZExtInst>(LHS)))
118+
if (!LHS || !canBeSignExtend(LHS))
118119
return false;
119120

120121
Value *LHSSrc = LHS->getOperand(0);
@@ -135,13 +136,6 @@ bool RISCVCodeGenPrepare::visitAnd(BinaryOperator &BO) {
135136
if (!isUInt<32>(C) || isInt<12>(C) || !isInt<12>(SignExtend64<32>(C)))
136137
return false;
137138

138-
// If we can determine the sign bit of the input is 0, we can replace the
139-
// And mask constant.
140-
if (!isImpliedByDomCondition(ICmpInst::ICMP_SGE, LHSSrc,
141-
Constant::getNullValue(LHSSrc->getType()),
142-
LHS, *DL).value_or(false))
143-
return false;
144-
145139
// Sign extend the constant and replace the And operand.
146140
C = SignExtend64<32>(C);
147141
BO.setOperand(1, ConstantInt::get(LHS->getType(), C));

llvm/test/CodeGen/RISCV/riscv-codegenprepare.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ define void @test1(ptr nocapture noundef %a, i32 noundef signext %n) {
99
; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[N:%.*]], 0
1010
; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
1111
; CHECK: for.body.preheader:
12-
; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = sext i32 [[N]] to i64
12+
; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext nneg i32 [[N]] to i64
1313
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
1414
; CHECK: for.cond.cleanup.loopexit:
1515
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
@@ -60,7 +60,7 @@ define void @test2(ptr nocapture noundef %a, i32 noundef signext %n) {
6060
; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[N:%.*]], 0
6161
; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
6262
; CHECK: for.body.preheader:
63-
; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = sext i32 [[N]] to i64
63+
; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext nneg i32 [[N]] to i64
6464
; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[WIDE_TRIP_COUNT]], 1
6565
; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[N]], 1
6666
; CHECK-NEXT: br i1 [[TMP0]], label [[FOR_COND_CLEANUP_LOOPEXIT_UNR_LCSSA:%.*]], label [[FOR_BODY_PREHEADER_NEW:%.*]]

0 commit comments

Comments
 (0)