Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -150,6 +150,12 @@ bool FromLegal = FromWidth == 1 || DL.isLegalInteger(FromWidth); bool ToLegal = ToWidth == 1 || DL.isLegalInteger(ToWidth); + // If the type to convert to is i8 or i16 (a very common case), then + // we convert whether it is a legal type or not. This can often open up + // extra combine opportunities. + if (FromLegal && ToWidth < FromWidth && (ToWidth == 8 || ToWidth == 16)) + return true; + // If this is a legal integer from type, and the result would be an illegal // type, don't do the transformation. if (FromLegal && !ToLegal) Index: test/Transforms/InstCombine/should-change-type.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/should-change-type.ll @@ -0,0 +1,45 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" + +; Tests for removing zext/trunk from/to i8 and i16, even if it is not a +; legal type. + +define i8 @test1(i8 %x, i8 %y) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[C:%.*]] = add i8 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret i8 [[C]] +; + %xz = zext i8 %x to i32 + %yz = zext i8 %y to i32 + %c = add i32 %xz, %yz + %d = trunc i32 %c to i8 + ret i8 %d +} + +define i16 @test2(i16 %x, i16 %y) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[C:%.*]] = add i16 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret i16 [[C]] +; + %xz = zext i16 %x to i32 + %yz = zext i16 %y to i32 + %c = add i32 %xz, %yz + %d = trunc i32 %c to i16 + ret i16 %d +} + +define i9 @test3(i9 %x, i9 %y) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[XZ:%.*]] = zext i9 [[X:%.*]] to i32 +; CHECK-NEXT: [[YZ:%.*]] = zext i9 [[Y:%.*]] to i32 +; CHECK-NEXT: [[C:%.*]] = add nuw nsw i32 [[XZ]], [[YZ]] +; CHECK-NEXT: [[D:%.*]] = trunc i32 [[C]] to i9 +; CHECK-NEXT: ret i9 [[D]] +; + %xz = zext i9 %x to i32 + %yz = zext i9 %y to i32 + %c = add i32 %xz, %yz + %d = trunc i32 %c to i9 + ret i9 %d +}