Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -144,11 +144,15 @@ /// We don't want to convert from a legal to an illegal type or from a smaller /// to a larger illegal type. A width of '1' is always treated as a legal type /// because i1 is a fundamental type in IR, and there are many specialized -/// optimizations for i1 types. +/// optimizations for i1 types. Widths or 8, 16 or 32 are equally treated as +/// legal to convert to, in order to open up more combining opportunities. +/// NOTE: this treats i8, i16 and i32 specially, due to them being so common +/// from frontend languages. bool InstCombiner::shouldChangeType(unsigned FromWidth, unsigned ToWidth) const { bool FromLegal = FromWidth == 1 || DL.isLegalInteger(FromWidth); - bool ToLegal = ToWidth == 1 || DL.isLegalInteger(ToWidth); + bool ToLegal = ToWidth == 1 || ToWidth == 8 || ToWidth == 16 || + ToWidth == 32 || DL.isLegalInteger(ToWidth); // If this is a legal integer from type, and the result would be an illegal // type, don't do the transformation. Index: test/Transforms/InstCombine/2010-11-01-lshr-mask.ll =================================================================== --- test/Transforms/InstCombine/2010-11-01-lshr-mask.ll +++ test/Transforms/InstCombine/2010-11-01-lshr-mask.ll @@ -1,13 +1,12 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -instcombine -S < %s | FileCheck %s ; define i32 @main(i32 %argc) { ; CHECK-LABEL: @main( -; CHECK-NEXT: [[TMP3151:%.*]] = trunc i32 %argc to i8 -; CHECK-NEXT: [[TMP1:%.*]] = shl i8 [[TMP3151]], 5 -; CHECK-NEXT: [[TMP4126:%.*]] = and i8 [[TMP1]], 64 -; CHECK-NEXT: [[TMP4127:%.*]] = xor i8 [[TMP4126]], 64 -; CHECK-NEXT: [[TMP4086:%.*]] = zext i8 [[TMP4127]] to i32 +; CHECK-NEXT: [[TMP3163:%.*]] = shl i32 %argc, 5 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[TMP3163]], 64 +; CHECK-NEXT: [[TMP4086:%.*]] = xor i32 [[TMP1]], 64 ; CHECK-NEXT: ret i32 [[TMP4086]] ; %tmp3151 = trunc i32 %argc to i8 Index: test/Transforms/InstCombine/select-bitext.ll =================================================================== --- test/Transforms/InstCombine/select-bitext.ll +++ test/Transforms/InstCombine/select-bitext.ll @@ -112,8 +112,9 @@ define i32 @trunc_sel_smaller_sext(i64 %a, i1 %cmp) { ; CHECK-LABEL: @trunc_sel_smaller_sext( -; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 %a to i16 -; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[TRUNC]] to i32 +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 %a to i32 +; CHECK-NEXT: [[SEXT:%.*]] = shl i32 [[TRUNC]], 16 +; CHECK-NEXT: [[TMP1:%.*]] = ashr exact i32 [[SEXT]], 16 ; CHECK-NEXT: [[EXT:%.*]] = select i1 %cmp, i32 [[TMP1]], i32 42 ; CHECK-NEXT: ret i32 [[EXT]] ; Index: test/Transforms/InstCombine/should-change-type.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/should-change-type.ll @@ -0,0 +1,57 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "n64" + +; Tests for removing zext/trunc from/to i8, i16 and i32, 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 i64 + %yz = zext i8 %y to i64 + %c = add i64 %xz, %yz + %d = trunc i64 %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 i64 + %yz = zext i16 %y to i64 + %c = add i64 %xz, %yz + %d = trunc i64 %c to i16 + ret i16 %d +} + +define i32 @test3(i32 %x, i32 %y) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[C:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[C]] +; + %xz = zext i32 %x to i64 + %yz = zext i32 %y to i64 + %c = add i64 %xz, %yz + %d = trunc i64 %c to i32 + ret i32 %d +} + +define i9 @test4(i9 %x, i9 %y) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: [[XZ:%.*]] = zext i9 [[X:%.*]] to i64 +; CHECK-NEXT: [[YZ:%.*]] = zext i9 [[Y:%.*]] to i64 +; CHECK-NEXT: [[C:%.*]] = add nuw nsw i64 [[XZ]], [[YZ]] +; CHECK-NEXT: [[D:%.*]] = trunc i64 [[C]] to i9 +; CHECK-NEXT: ret i9 [[D]] +; + %xz = zext i9 %x to i64 + %yz = zext i9 %y to i64 + %c = add i64 %xz, %yz + %d = trunc i64 %c to i9 + ret i9 %d +}