Index: lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCasts.cpp +++ lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -14,6 +14,7 @@ #include "llvm/ADT/SetVector.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/DemandedBits.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/PatternMatch.h" @@ -1441,7 +1442,16 @@ A = Builder.CreateShl(A, ShAmtV, CI.getName()); return BinaryOperator::CreateAShr(A, ShAmtV); } + // If we are not using any of the sign bits, convert to a zext + DemandedBits DB(*CI.getParent()->getParent(), AC, DT); + APInt Demanded = DB.getDemandedBits(&CI); + uint32_t SrcBitSize = SrcTy->getScalarSizeInBits(); + uint32_t DestBitSize = DestTy->getScalarSizeInBits(); + if(Demanded.countLeadingZeros() >= (DestBitSize - SrcBitSize)){ + Value *ZExt = Builder.CreateZExt(Src, DestTy); + return replaceInstUsesWith(CI, ZExt); + } return nullptr; } Index: test/Transforms/InstCombine/cast.ll =================================================================== --- test/Transforms/InstCombine/cast.ll +++ test/Transforms/InstCombine/cast.ll @@ -1559,3 +1559,21 @@ %5 = zext i8 %4 to i32 ret i32 %5 } + +; We should be able to convert the sext to zext here. +; CHECK-LABEL: define i16 @foo(i16 %a) { +; CHECK: %and = and i16 %a, -256 +; CHECK-NEXT: %lsr = lshr i16 %a, 8 +; CHECK-NEXT: %or = or i16 %and, %lsr +; CHECK-NEXT: ret i16 %or + +define i16 @foo(i16 %a) { +entry: + %ext = sext i16 %a to i32 + %and = and i32 %ext, 65280 + %lsr = lshr i32 %ext, 8 + %and2 = and i32 %lsr, 255 + %or = or i32 %and, %and2 + %ret = trunc i32 %or to i16 + ret i16 %ret +}