diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2618,13 +2618,31 @@ if (SelType->isIntOrIntVectorTy(1) && TrueVal->getType() == CondVal->getType()) { - if (match(TrueVal, m_One()) && - (EnableUnsafeSelectTransform || impliesPoison(FalseVal, CondVal))) { + auto IsSafeToConvert = [&](Value *OtherVal) { + if (impliesPoison(OtherVal, CondVal)) + return true; + + if (!EnableUnsafeSelectTransform) + return false; + + // We block this transformation if OtherVal or its operand can create + // poison. See PR49688 + if (auto *Op = dyn_cast(OtherVal)) { + if (canCreatePoison(Op)) + return false; + if (propagatesPoison(Op) && + llvm::any_of(Op->operand_values(), [](Value *V) { + return isa(V) ? canCreatePoison(cast(V)) : + false; })) + return false; + } + return true; + }; + if (match(TrueVal, m_One()) && IsSafeToConvert(FalseVal)) { // Change: A = select B, true, C --> A = or B, C return BinaryOperator::CreateOr(CondVal, FalseVal); } - if (match(FalseVal, m_Zero()) && - (EnableUnsafeSelectTransform || impliesPoison(TrueVal, CondVal))) { + if (match(FalseVal, m_Zero()) && IsSafeToConvert(TrueVal)) { // Change: A = select B, C, false --> A = and B, C return BinaryOperator::CreateAnd(CondVal, TrueVal); } diff --git a/llvm/test/Transforms/InstCombine/and-fcmp.ll b/llvm/test/Transforms/InstCombine/and-fcmp.ll --- a/llvm/test/Transforms/InstCombine/and-fcmp.ll +++ b/llvm/test/Transforms/InstCombine/and-fcmp.ll @@ -73,10 +73,13 @@ ret i1 %r } +; TODO: this should be fixed using freeze define i1 @PR41069_commute_logical(i1 %z, float %c, float %d) { ; CHECK-LABEL: @PR41069_commute_logical( -; CHECK-NEXT: [[TMP1:%.*]] = fcmp ninf ord float [[D:%.*]], [[C:%.*]] -; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP1]], [[Z:%.*]] +; CHECK-NEXT: [[ORD1:%.*]] = fcmp ninf ord float [[C:%.*]], 0.000000e+00 +; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD1]], [[Z:%.*]] +; CHECK-NEXT: [[ORD2:%.*]] = fcmp reassoc ninf ord float [[D:%.*]], 0.000000e+00 +; CHECK-NEXT: [[R:%.*]] = select i1 [[ORD2]], i1 [[AND]], i1 false ; CHECK-NEXT: ret i1 [[R]] ; %ord1 = fcmp ninf ord float %c, 0.0 diff --git a/llvm/test/Transforms/InstCombine/onehot_merge.ll b/llvm/test/Transforms/InstCombine/onehot_merge.ll --- a/llvm/test/Transforms/InstCombine/onehot_merge.ll +++ b/llvm/test/Transforms/InstCombine/onehot_merge.ll @@ -468,7 +468,7 @@ ; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] ; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]] ; CHECK-NEXT: ret i1 [[OR]] ; %t0 = shl i32 1, %c1 @@ -506,7 +506,7 @@ ; CHECK-NEXT: [[T2:%.*]] = icmp ne i32 [[T1]], 0 ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] ; CHECK-NEXT: [[T4:%.*]] = icmp slt i32 [[T3]], 0 -; CHECK-NEXT: [[OR:%.*]] = and i1 [[T2]], [[T4]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 [[T4]], i1 false ; CHECK-NEXT: ret i1 [[OR]] ; %t0 = shl i32 1, %c1 @@ -535,13 +535,15 @@ ret i1 %or } +; %t2 can be poison where as %t0 isn't; merging these two is unsafe. define i1 @foo1_and_signbit_lshr_without_shifting_signbit_both_sides_logical(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_and_signbit_lshr_without_shifting_signbit_both_sides_logical( ; CHECK-NEXT: [[T0:%.*]] = shl i32 [[K:%.*]], [[C1:%.*]] +; CHECK-NEXT: [[T1:%.*]] = icmp sgt i32 [[T0]], -1 ; CHECK-NEXT: [[T2:%.*]] = shl i32 [[K]], [[C2:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[T0]], [[T2]] -; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP1]], -1 -; CHECK-NEXT: ret i1 [[TMP2]] +; CHECK-NEXT: [[T3:%.*]] = icmp sgt i32 [[T2]], -1 +; CHECK-NEXT: [[OR:%.*]] = select i1 [[T1]], i1 true, i1 [[T3]] +; CHECK-NEXT: ret i1 [[OR]] ; %t0 = shl i32 %k, %c1 %t1 = icmp sgt i32 %t0, -1 @@ -567,13 +569,15 @@ ret i1 %or } +; %t2 can be poison where as %t0 isn't; merging these two is unsafe. define i1 @foo1_or_signbit_lshr_without_shifting_signbit_both_sides_logical(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_or_signbit_lshr_without_shifting_signbit_both_sides_logical( ; CHECK-NEXT: [[T0:%.*]] = shl i32 [[K:%.*]], [[C1:%.*]] +; CHECK-NEXT: [[T1:%.*]] = icmp slt i32 [[T0]], 0 ; CHECK-NEXT: [[T2:%.*]] = shl i32 [[K]], [[C2:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[T0]], [[T2]] -; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0 -; CHECK-NEXT: ret i1 [[TMP2]] +; CHECK-NEXT: [[T3:%.*]] = icmp slt i32 [[T2]], 0 +; CHECK-NEXT: [[OR:%.*]] = select i1 [[T1]], i1 [[T3]], i1 false +; CHECK-NEXT: ret i1 [[OR]] ; %t0 = shl i32 %k, %c1 %t1 = icmp slt i32 %t0, 0 @@ -886,7 +890,7 @@ ; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] ; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]] ; CHECK-NEXT: ret i1 [[OR]] ; %t0 = shl i32 1, %c1 @@ -929,7 +933,7 @@ ; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] ; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]] ; CHECK-NEXT: ret i1 [[OR]] ; %t0 = shl i32 1, %c1 @@ -972,7 +976,7 @@ ; CHECK-NEXT: store i1 [[T2]], i1* [[P:%.*]], align 1 ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] ; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]] ; CHECK-NEXT: ret i1 [[OR]] ; %t0 = shl i32 1, %c1 @@ -1015,7 +1019,7 @@ ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] ; CHECK-NEXT: store i32 [[T3]], i32* [[P:%.*]], align 4 ; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]] ; CHECK-NEXT: ret i1 [[OR]] ; %t0 = shl i32 1, %c1 @@ -1058,7 +1062,7 @@ ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] ; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 ; CHECK-NEXT: store i1 [[T4]], i1* [[P:%.*]], align 1 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]] ; CHECK-NEXT: ret i1 [[OR]] ; %t0 = shl i32 1, %c1 @@ -1100,7 +1104,7 @@ ; CHECK-NEXT: [[T2:%.*]] = icmp eq i32 [[T1]], 0 ; CHECK-NEXT: [[T3:%.*]] = shl i32 [[K]], [[C2:%.*]] ; CHECK-NEXT: [[T4:%.*]] = icmp sgt i32 [[T3]], -1 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[T2]], [[T4]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[T2]], i1 true, i1 [[T4]] ; CHECK-NEXT: ret i1 [[OR]] ; %t0 = shl i32 3, %c1 diff --git a/llvm/test/Transforms/InstCombine/pr49688.ll b/llvm/test/Transforms/InstCombine/pr49688.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/pr49688.ll @@ -0,0 +1,38 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +; %cmp should not vanish +define i1 @f(i32 %i1) { +; CHECK-LABEL: @f( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I1:%.*]], 0 +; CHECK-NEXT: [[SHR:%.*]] = lshr i32 7, [[I1]] +; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[SHR]], [[I1]] +; CHECK-NEXT: [[I2:%.*]] = select i1 [[CMP]], i1 true, i1 [[CMP4]] +; CHECK-NEXT: ret i1 [[I2]] +; +entry: + %cmp = icmp slt i32 %i1, 0 + %shr = ashr i32 7, %i1 + %cmp4 = icmp sgt i32 %i1, %shr + %i2 = select i1 %cmp, i1 true, i1 %cmp4 + ret i1 %i2 +} + +; %cmp should not vanish +define i32 @f2(i32 signext %g, i32 zeroext %h) { +; CHECK-LABEL: @f2( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[G:%.*]], 0 +; CHECK-NEXT: [[SHR:%.*]] = lshr i32 7, [[H:%.*]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[SHR]], [[G]] +; CHECK-NEXT: [[DOT0:%.*]] = select i1 [[CMP]], i1 true, i1 [[CMP1]] +; CHECK-NEXT: [[LOR_EXT:%.*]] = zext i1 [[DOT0]] to i32 +; CHECK-NEXT: ret i32 [[LOR_EXT]] +; + %cmp = icmp slt i32 %g, 0 + %shr = ashr i32 7, %h + %cmp1 = icmp sgt i32 %g, %shr + %.0 = select i1 %cmp, i1 true, i1 %cmp1 + %lor.ext = zext i1 %.0 to i32 + ret i32 %lor.ext +} diff --git a/llvm/test/Transforms/InstCombine/signed-truncation-check.ll b/llvm/test/Transforms/InstCombine/signed-truncation-check.ll --- a/llvm/test/Transforms/InstCombine/signed-truncation-check.ll +++ b/llvm/test/Transforms/InstCombine/signed-truncation-check.ll @@ -606,7 +606,7 @@ ; CHECK-NEXT: call void @use32(i32 [[T4]]) ; CHECK-NEXT: [[T5:%.*]] = icmp eq i32 [[T4]], [[ARG]] ; CHECK-NEXT: call void @use1(i1 [[T5]]) -; CHECK-NEXT: [[T6:%.*]] = and i1 [[T2]], [[T5]] +; CHECK-NEXT: [[T6:%.*]] = select i1 [[T2]], i1 [[T5]], i1 false ; CHECK-NEXT: ret i1 [[T6]] ; %t1 = trunc i32 %arg to i8 diff --git a/llvm/test/Transforms/InstCombine/widenable-conditions.ll b/llvm/test/Transforms/InstCombine/widenable-conditions.ll --- a/llvm/test/Transforms/InstCombine/widenable-conditions.ll +++ b/llvm/test/Transforms/InstCombine/widenable-conditions.ll @@ -20,7 +20,7 @@ define i1 @test1_logical(i1 %a, i1 %b) { ; CHECK-LABEL: @test1_logical( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[LHS:%.*]] = and i1 [[WC]], [[B:%.*]] +; CHECK-NEXT: [[LHS:%.*]] = select i1 [[B:%.*]], i1 [[WC]], i1 false ; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[A:%.*]] ; CHECK-NEXT: ret i1 [[AND]] ; @@ -49,7 +49,7 @@ define i1 @test1b_logical(i1 %a, i1 %b) { ; CHECK-LABEL: @test1b_logical( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[LHS:%.*]] = and i1 [[WC]], [[B:%.*]] +; CHECK-NEXT: [[LHS:%.*]] = select i1 [[B:%.*]], i1 [[WC]], i1 false ; CHECK-NEXT: call void @use(i1 [[LHS]]) ; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[A:%.*]] ; CHECK-NEXT: ret i1 [[AND]] @@ -87,7 +87,7 @@ ; CHECK-NEXT: call void @use(i1 [[B:%.*]]) ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: call void @use(i1 [[WC]]) -; CHECK-NEXT: [[LHS:%.*]] = and i1 [[WC]], [[B]] +; CHECK-NEXT: [[LHS:%.*]] = select i1 [[B]], i1 [[WC]], i1 false ; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[A]] ; CHECK-NEXT: ret i1 [[AND]] ; @@ -147,7 +147,7 @@ ; CHECK-LABEL: @test3_logical( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[LHS:%.*]] = and i1 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[RHS:%.*]] = and i1 [[WC]], [[C:%.*]] +; CHECK-NEXT: [[RHS:%.*]] = select i1 [[C:%.*]], i1 [[WC]], i1 false ; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[RHS]] ; CHECK-NEXT: ret i1 [[AND]] ; @@ -178,7 +178,7 @@ ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[LHS:%.*]] = and i1 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[RHS:%.*]] = and i1 [[WC]], [[C:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[RHS]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[LHS]], i1 [[RHS]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() @@ -225,7 +225,7 @@ ; CHECK-LABEL: @test6_logical( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[AND:%.*]] = and i1 [[WC]], [[WC2]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[WC]], i1 [[WC2]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() @@ -254,7 +254,7 @@ ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: call void @use(i1 [[WC]]) ; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[AND:%.*]] = and i1 [[WC]], [[WC2]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[WC]], i1 [[WC2]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() @@ -284,7 +284,7 @@ ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: call void @use(i1 [[WC2]]) -; CHECK-NEXT: [[AND:%.*]] = and i1 [[WC]], [[WC2]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[WC]], i1 [[WC2]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() diff --git a/llvm/test/Transforms/PhaseOrdering/unsigned-multiply-overflow-check.ll b/llvm/test/Transforms/PhaseOrdering/unsigned-multiply-overflow-check.ll --- a/llvm/test/Transforms/PhaseOrdering/unsigned-multiply-overflow-check.ll +++ b/llvm/test/Transforms/PhaseOrdering/unsigned-multiply-overflow-check.ll @@ -93,10 +93,10 @@ ; INSTCOMBINEONLY: bb2: ; INSTCOMBINEONLY-NEXT: [[UMUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG]], i64 [[ARG1:%.*]]) ; INSTCOMBINEONLY-NEXT: [[UMUL_OV:%.*]] = extractvalue { i64, i1 } [[UMUL]], 1 -; INSTCOMBINEONLY-NEXT: [[PHITMP:%.*]] = xor i1 [[UMUL_OV]], true +; INSTCOMBINEONLY-NEXT: [[PHI_BO:%.*]] = xor i1 [[UMUL_OV]], true ; INSTCOMBINEONLY-NEXT: br label [[BB5]] ; INSTCOMBINEONLY: bb5: -; INSTCOMBINEONLY-NEXT: [[T6:%.*]] = phi i1 [ true, [[BB:%.*]] ], [ [[PHITMP]], [[BB2]] ] +; INSTCOMBINEONLY-NEXT: [[T6:%.*]] = phi i1 [ true, [[BB:%.*]] ], [ [[PHI_BO]], [[BB2]] ] ; INSTCOMBINEONLY-NEXT: ret i1 [[T6]] ; ; INSTCOMBINESIMPLIFYCFGONLY-LABEL: @will_overflow( @@ -104,16 +104,16 @@ ; INSTCOMBINESIMPLIFYCFGONLY-NEXT: [[T0:%.*]] = icmp eq i64 [[ARG:%.*]], 0 ; INSTCOMBINESIMPLIFYCFGONLY-NEXT: [[UMUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG]], i64 [[ARG1:%.*]]) ; INSTCOMBINESIMPLIFYCFGONLY-NEXT: [[UMUL_OV:%.*]] = extractvalue { i64, i1 } [[UMUL]], 1 -; INSTCOMBINESIMPLIFYCFGONLY-NEXT: [[PHITMP:%.*]] = xor i1 [[UMUL_OV]], true -; INSTCOMBINESIMPLIFYCFGONLY-NEXT: [[T6:%.*]] = select i1 [[T0]], i1 true, i1 [[PHITMP]] +; INSTCOMBINESIMPLIFYCFGONLY-NEXT: [[PHI_BO:%.*]] = xor i1 [[UMUL_OV]], true +; INSTCOMBINESIMPLIFYCFGONLY-NEXT: [[T6:%.*]] = select i1 [[T0]], i1 true, i1 [[PHI_BO]] ; INSTCOMBINESIMPLIFYCFGONLY-NEXT: ret i1 [[T6]] ; ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-LABEL: @will_overflow( ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT: bb: ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT: [[UMUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[ARG:%.*]], i64 [[ARG1:%.*]]) ; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT: [[UMUL_OV:%.*]] = extractvalue { i64, i1 } [[UMUL]], 1 -; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT: [[PHITMP:%.*]] = xor i1 [[UMUL_OV]], true -; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT: ret i1 [[PHITMP]] +; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT: [[PHI_BO:%.*]] = xor i1 [[UMUL_OV]], true +; INSTCOMBINESIMPLIFYCFGINSTCOMBINE-NEXT: ret i1 [[PHI_BO]] ; bb: %t0 = icmp eq i64 %arg, 0