diff --git a/llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp b/llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp --- a/llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp +++ b/llvm/lib/Target/RISCV/RISCVCodeGenPrepare.cpp @@ -29,6 +29,8 @@ #define PASS_NAME "RISCV CodeGenPrepare" STATISTIC(NumZExtToSExt, "Number of SExt instructions converted to ZExt"); +STATISTIC(NumZExtToSExtNonNeg, + "Number of SExt non negative value instructions converted to ZExt"); namespace { @@ -83,7 +85,29 @@ ++NumZExtToSExt; return true; } + // Look for a non negative zext(value) and replace it with sext. + if (isKnownNonNegative(Src, *DL)) { + auto SExt = new SExtInst(Src, ZExt.getType(), "", &ZExt); + SExt->takeName(&ZExt); + SExt->setDebugLoc(ZExt.getDebugLoc()); + + ZExt.replaceAllUsesWith(SExt); + ZExt.eraseFromParent(); + ++NumZExtToSExtNonNeg; + return true; + } + // Look for zext instructions that have the nneg flag. + if (ZExt.hasNonNeg()){ + auto SExt = new SExtInst(Src, ZExt.getType(), "", &ZExt); + SExt->takeName(&ZExt); + SExt->setDebugLoc(ZExt.getDebugLoc()); + + ZExt.replaceAllUsesWith(SExt); + ZExt.eraseFromParent(); + ++NumZExtToSExtNonNeg; + return true; + } // Convert (zext (abs(i32 X, i1 1))) -> (sext (abs(i32 X, i1 1))). If abs of // INT_MIN is poison, the sign bit is zero. using namespace PatternMatch; diff --git a/llvm/test/CodeGen/RISCV/riscv-codegenprepare-asm.ll b/llvm/test/CodeGen/RISCV/riscv-codegenprepare-asm.ll --- a/llvm/test/CodeGen/RISCV/riscv-codegenprepare-asm.ll +++ b/llvm/test/CodeGen/RISCV/riscv-codegenprepare-asm.ll @@ -125,3 +125,15 @@ %niter.ncmp.1 = icmp eq i64 %niter.next.1, %unroll_iter br i1 %niter.ncmp.1, label %for.cond.cleanup.loopexit.unr-lcssa, label %for.body } + +define i64 @test3(i32 noundef %a){ +; CHECK-LABEL: test3: +; CHECK: # %bb.0: +; CHECK-NEXT: sext.w a0, a0 +; CHECK-NEXT: addi a0, a0, 5 +; CHECK-NEXT: ret + + %ext = zext nneg i32 %a to i64 + %added = add i64 %ext, 5 + ret i64 %added +} diff --git a/llvm/test/CodeGen/RISCV/riscv-codegenprepare.ll b/llvm/test/CodeGen/RISCV/riscv-codegenprepare.ll --- a/llvm/test/CodeGen/RISCV/riscv-codegenprepare.ll +++ b/llvm/test/CodeGen/RISCV/riscv-codegenprepare.ll @@ -142,3 +142,31 @@ %niter.ncmp.1 = icmp eq i64 %niter.next.1, %unroll_iter br i1 %niter.ncmp.1, label %for.cond.cleanup.loopexit.unr-lcssa, label %for.body } + +declare void @llvm.assume(i1 %assume); +define i64 @test3(i32 noundef signext %a){ +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[ASSUME:%.*]] = icmp sge i32 [[A:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[ASSUME]]) +; CHECK-NEXT: [[EXT:%.*]] = zext i32 [[A]] to i64 +; CHECK-NEXT: ret i64 [[EXT]] +; + %assume = icmp sge i32 %a, 0; + call void @llvm.assume(i1 %assume) + %ext = zext i32 %a to i64 + ret i64 %ext +} + + +define i64 @test4(i32 noundef %a){ +; CHECK-LABEL: @test4( +; CHECK-NEXT: [[EXT:%.*]] = sext i32 [[A:%.*]] to i64 +; CHECK-NEXT: [[ADDED:%.*]] = add i64 [[EXT]], 5 +; CHECK-NEXT: ret i64 [[EXT]] +; + %ext = zext nneg i32 %a to i64 + %added = add i64 %ext, 5 + ret i64 %ext; +} + +