[BDCE] SExt -> ZExt when no sign bits is used and instruction has multiple uses

Summary: This allows to convert any SExt to a ZExt when we know none of the extended bits are used, specially in cases where there are multiple uses of the value.

Reviewers: dmgreen, eli.friedman, spatel, lebedev.ri, nikic

Reviewed By: lebedev.ri, nikic

Subscribers: hiraditya, dmgreen, craig.topper, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D60413
This commit is contained in:
Diogo Sampaio 2020-07-10 08:01:04 +01:00
parent 16997459bc
commit a99cdef4f6
2 changed files with 32 additions and 10 deletions

View File

@ -9,7 +9,8 @@
// This file implements the Bit-Tracking Dead Code Elimination pass. Some
// instructions (shifts, some ands, ors, etc.) kill some of their input bits.
// We track these dead bits and remove instructions that compute only these
// dead bits.
// dead bits. We also simplify sext that generates unused extension bits,
// converting it to a zext.
//
//===----------------------------------------------------------------------===//
@ -19,6 +20,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/DemandedBits.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/InitializePasses.h"
@ -33,6 +35,8 @@ using namespace llvm;
STATISTIC(NumRemoved, "Number of instructions removed (unused)");
STATISTIC(NumSimplified, "Number of instructions trivialized (dead bits)");
STATISTIC(NumSExt2ZExt,
"Number of sign extension instructions converted to zero extension");
/// If an instruction is trivialized (dead), then the chain of users of that
/// instruction may need to be cleared of assumptions that can no longer be
@ -109,6 +113,24 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
continue;
}
// Convert SExt into ZExt if none of the extension bits is required
if (SExtInst *SE = dyn_cast<SExtInst>(&I)) {
APInt Demanded = DB.getDemandedBits(SE);
const uint32_t SrcBitSize = SE->getSrcTy()->getScalarSizeInBits();
auto *const DstTy = SE->getDestTy();
const uint32_t DestBitSize = DstTy->getScalarSizeInBits();
if (Demanded.countLeadingZeros() >= (DestBitSize - SrcBitSize)) {
clearAssumptionsOfUsers(SE, DB);
IRBuilder<> Builder(SE);
I.replaceAllUsesWith(
Builder.CreateZExt(SE->getOperand(0), DstTy, SE->getName()));
Worklist.push_back(SE);
Changed = true;
NumSExt2ZExt++;
continue;
}
}
for (Use &U : I.operands()) {
// DemandedBits only detects dead integer uses.
if (!U->getType()->isIntOrIntVectorTy())

View File

@ -1,11 +1,11 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -o - -bdce -S %s | FileCheck %s
; RUN: opt -S -bdce < %s | FileCheck %s
define i32 @ZEXT_0(i16 %a) {
; CHECK-LABEL: @ZEXT_0(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[A:%.*]] to i32
; CHECK-NEXT: [[AND:%.*]] = and i32 [[EXT]], 65280
; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT]], 8
; CHECK-NEXT: [[EXT1:%.*]] = zext i16 [[A:%.*]] to i32
; CHECK-NEXT: [[AND:%.*]] = and i32 [[EXT1]], 65280
; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT1]], 8
; CHECK-NEXT: [[AND2:%.*]] = and i32 [[LSR]], 255
; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND2]]
; CHECK-NEXT: ret i32 [[OR]]
@ -22,10 +22,10 @@ entry:
define i32 @ZEXT_1(i16 %a) {
; CHECK-LABEL: @ZEXT_1(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[A:%.*]] to i32
; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT]], 8
; CHECK-NEXT: [[EXT1:%.*]] = zext i16 [[A:%.*]] to i32
; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT1]], 8
; CHECK-NEXT: [[AND2:%.*]] = and i32 [[LSR]], 255
; CHECK-NEXT: [[AND:%.*]] = or i32 [[EXT]], -65536
; CHECK-NEXT: [[AND:%.*]] = or i32 [[EXT1]], -65536
; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND2]]
; CHECK-NEXT: ret i32 [[OR]]
;
@ -99,8 +99,8 @@ entry:
define i16 @clear_assumptions(i8 %x, i16 %y) {
; CHECK-LABEL: @clear_assumptions(
; CHECK-NEXT: [[EXT:%.*]] = sext i8 [[X:%.*]] to i16
; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[EXT]], [[Y:%.*]]
; CHECK-NEXT: [[EXT1:%.*]] = zext i8 [[X:%.*]] to i16
; CHECK-NEXT: [[ADD:%.*]] = add i16 [[EXT1]], [[Y:%.*]]
; CHECK-NEXT: [[AND:%.*]] = and i16 [[ADD]], 255
; CHECK-NEXT: ret i16 [[AND]]
;