Index: lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCasts.cpp +++ lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1053,11 +1053,17 @@ if (CI.hasOneUse() && isa(CI.user_back())) return nullptr; + Value *Src = CI.getOperand(0); + + // If this zero extend is of phi, keep it that way. + // This may allow further simplifications. + if (CI.hasOneUse() && isa(Src)) + return nullptr; + // If one of the common conversion will work, do it. if (Instruction *Result = commonCastTransforms(CI)) return Result; - Value *Src = CI.getOperand(0); Type *SrcTy = Src->getType(), *DestTy = CI.getType(); // Attempt to extend the entire input expression tree to the destination @@ -1324,10 +1330,16 @@ if (CI.hasOneUse() && isa(CI.user_back())) return nullptr; + Value *Src = CI.getOperand(0); + + // If this zero extend is of phi, keep it that way. + // This may allow further simplifications. + if (CI.hasOneUse() && isa(Src)) + return nullptr; + if (Instruction *I = commonCastTransforms(CI)) return I; - Value *Src = CI.getOperand(0); Type *SrcTy = Src->getType(), *DestTy = CI.getType(); // If we know that the value being extended is positive, we can use a zext Index: test/Transforms/InstCombine/ext-of-select-of-bittest.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/ext-of-select-of-bittest.ll @@ -0,0 +1,130 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +; https://bugs.llvm.org/show_bug.cgi?id=17564 + +; If we thread zext/sext into phi, we won't be able to get rid of select +; later on, so don't do that. + +define zeroext i1 @just_phi(i32) { +; CHECK-LABEL: @just_phi( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] +; CHECK: [[TMP5:%.*]] = and i32 [[TMP0]], 4 +; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0 +; CHECK-NEXT: br label [[TMP7]] +; CHECK: [[TMP8:%.*]] = phi i1 [ true, [[TMP1:%.*]] ], [ [[TMP6]], [[TMP4]] ] +; CHECK-NEXT: ret i1 [[TMP8]] +; + %2 = and i32 %0, 1 + %3 = icmp ne i32 %2, 0 + br i1 %3, label %7, label %4 + + %5 = and i32 %0, 4 + %6 = icmp ne i32 %5, 0 + br label %7 + + %8 = phi i1 [ true, %1 ], [ %6, %4 ] + ret i1 %8 +} + +define i32 @zext_of_phi(i32) { +; CHECK-LABEL: @zext_of_phi( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] +; CHECK: [[TMP5:%.*]] = and i32 [[TMP0]], 4 +; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0 +; CHECK-NEXT: br label [[TMP7]] +; CHECK: [[TMP8:%.*]] = phi i1 [ true, [[TMP1:%.*]] ], [ [[TMP6]], [[TMP4]] ] +; CHECK-NEXT: [[TMP9:%.*]] = zext i1 [[TMP8]] to i32 +; CHECK-NEXT: ret i32 [[TMP9]] +; + %2 = and i32 %0, 1 + %3 = icmp ne i32 %2, 0 + br i1 %3, label %7, label %4 + + %5 = and i32 %0, 4 + %6 = icmp ne i32 %5, 0 + br label %7 + + %8 = phi i1 [ true, %1 ], [ %6, %4 ] + %9 = zext i1 %8 to i32 + ret i32 %9 +} + +define i32 @sext_of_phi(i32) { +; CHECK-LABEL: @sext_of_phi( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 1 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] +; CHECK: [[TMP5:%.*]] = and i32 [[TMP0]], 4 +; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0 +; CHECK-NEXT: br label [[TMP7]] +; CHECK: [[TMP8:%.*]] = phi i1 [ true, [[TMP1:%.*]] ], [ [[TMP6]], [[TMP4]] ] +; CHECK-NEXT: [[TMP9:%.*]] = sext i1 [[TMP8]] to i32 +; CHECK-NEXT: ret i32 [[TMP9]] +; + %2 = and i32 %0, 1 + %3 = icmp ne i32 %2, 0 + br i1 %3, label %7, label %4 + + %5 = and i32 %0, 4 + %6 = icmp ne i32 %5, 0 + br label %7 + + %8 = phi i1 [ true, %1 ], [ %6, %4 ] + %9 = sext i1 %8 to i32 + ret i32 %9 +} + +; After instcombine those ^ are transformed into these \/, +; which are then simplified into icmp. + +define zeroext i1 @just_select(i32) { +; CHECK-LABEL: @just_select( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 5 +; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 +; CHECK-NEXT: ret i1 [[TMP3]] +; + %2 = and i32 %0, 1 + %3 = icmp eq i32 %2, 0 + %4 = and i32 %0, 4 + %5 = icmp ne i32 %4, 0 + %6 = select i1 %3, i1 %5, i1 true + ret i1 %6 +} + +define i32 @zext_of_select(i32) { +; CHECK-LABEL: @zext_of_select( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 5 +; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32 +; CHECK-NEXT: ret i32 [[TMP4]] +; + %2 = and i32 %0, 1 + %3 = icmp eq i32 %2, 0 + %4 = and i32 %0, 4 + %5 = icmp ne i32 %4, 0 + %6 = select i1 %3, i1 %5, i1 true + %7 = zext i1 %6 to i32 + ret i32 %7 +} + + +define i32 @sext_of_select(i32) { +; CHECK-LABEL: @sext_of_select( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 5 +; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = sext i1 [[TMP3]] to i32 +; CHECK-NEXT: ret i32 [[TMP4]] +; + %2 = and i32 %0, 1 + %3 = icmp eq i32 %2, 0 + %4 = and i32 %0, 4 + %5 = icmp ne i32 %4, 0 + %6 = select i1 %3, i1 %5, i1 true + %7 = sext i1 %6 to i32 + ret i32 %7 +} Index: test/Transforms/InstCombine/icmp-div-constant.ll =================================================================== --- test/Transforms/InstCombine/icmp-div-constant.ll +++ test/Transforms/InstCombine/icmp-div-constant.ll @@ -9,15 +9,15 @@ define i32 @icmp_div(i16 %a, i16 %c) { ; CHECK-LABEL: @icmp_div( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 %a, 0 -; CHECK-NEXT: br i1 [[TOBOOL]], label %then, label %exit +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 +; CHECK-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: -; CHECK-NEXT: [[NOT_CMP:%.*]] = icmp eq i16 %c, 0 -; CHECK-NEXT: [[PHITMP1:%.*]] = sext i1 [[NOT_CMP]] to i32 -; CHECK-NEXT: br label %exit +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[C:%.*]], 0 +; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, %entry ], [ [[PHITMP1]], %then ] -; CHECK-NEXT: ret i32 [[PHI]] +; CHECK-NEXT: [[PHI:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[CMP]], [[THEN]] ] +; CHECK-NEXT: [[ADD:%.*]] = sext i1 [[PHI]] to i32 +; CHECK-NEXT: ret i32 [[ADD]] ; entry: %tobool = icmp eq i16 %a, 0 @@ -38,13 +38,12 @@ define i32 @icmp_div2(i16 %a, i16 %c) { ; CHECK-LABEL: @icmp_div2( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 %a, 0 -; CHECK-NEXT: br i1 [[TOBOOL]], label %then, label %exit +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 +; CHECK-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: -; CHECK-NEXT: br label %exit +; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, %entry ], [ 0, %then ] -; CHECK-NEXT: ret i32 [[PHI]] +; CHECK-NEXT: ret i32 -1 ; entry: %tobool = icmp eq i16 %a, 0 @@ -65,15 +64,15 @@ define i32 @icmp_div3(i16 %a, i16 %c) { ; CHECK-LABEL: @icmp_div3( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 %a, 0 -; CHECK-NEXT: br i1 [[TOBOOL]], label %then, label %exit +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 +; CHECK-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: -; CHECK-NEXT: [[NOT_CMP:%.*]] = icmp eq i16 %c, 0 -; CHECK-NEXT: [[PHITMP1:%.*]] = sext i1 [[NOT_CMP]] to i32 -; CHECK-NEXT: br label %exit +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[C:%.*]], 0 +; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, %entry ], [ [[PHITMP1]], %then ] -; CHECK-NEXT: ret i32 [[PHI]] +; CHECK-NEXT: [[PHI:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[CMP]], [[THEN]] ] +; CHECK-NEXT: [[ADD:%.*]] = sext i1 [[PHI]] to i32 +; CHECK-NEXT: ret i32 [[ADD]] ; entry: %tobool = icmp eq i16 %a, 0 Index: test/Transforms/InstCombine/icmp-mul-zext.ll =================================================================== --- test/Transforms/InstCombine/icmp-mul-zext.ll +++ test/Transforms/InstCombine/icmp-mul-zext.ll @@ -18,11 +18,11 @@ ; CHECK-NEXT: [[AND:%.*]] = and i64 [[MUL3]], [[TMP2]] ; CHECK-NEXT: [[CONV4:%.*]] = trunc i64 [[AND]] to i32 ; CHECK-NEXT: [[TOBOOL7:%.*]] = icmp eq i32 [[CONV4]], 0 -; CHECK-NEXT: [[PHITMP:%.*]] = zext i1 [[TOBOOL7]] to i32 ; CHECK-NEXT: br label [[LOR_END]] ; CHECK: lor.end: -; CHECK-NEXT: [[TMP3:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[PHITMP]], [[LOR_RHS]] ] -; CHECK-NEXT: ret i32 [[TMP3]] +; CHECK-NEXT: [[TMP3:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[TOBOOL7]], [[LOR_RHS]] ] +; CHECK-NEXT: [[CONV8:%.*]] = zext i1 [[TMP3]] to i32 +; CHECK-NEXT: ret i32 [[CONV8]] ; entry: %conv = zext i32 %0 to i64