; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" define i1 @test1(i1 %a, i1 %b) { ; CHECK-LABEL: @test1( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[LHS:%.*]] = and i1 [[WC]], [[B:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[A:%.*]] ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %lhs = and i1 %b, %wc %and = and i1 %lhs, %a ret i1 %and } define i1 @test1_logical(i1 %a, i1 %b) { ; CHECK-LABEL: @test1_logical( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[LHS:%.*]] = select i1 [[B:%.*]], i1 [[WC]], i1 false ; CHECK-NEXT: [[AND:%.*]] = select i1 [[LHS]], i1 [[A:%.*]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %lhs = select i1 %b, i1 %wc, i1 false %and = select i1 %lhs, i1 %a, i1 false ret i1 %and } ; Negative test - profitability of dropping WC from first use unclear define i1 @test1b(i1 %a, i1 %b) { ; CHECK-LABEL: @test1b( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[LHS:%.*]] = and i1 [[WC]], [[B:%.*]] ; CHECK-NEXT: call void @use(i1 [[LHS]]) ; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[A:%.*]] ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %lhs = and i1 %b, %wc call void @use(i1 %lhs) %and = and i1 %lhs, %a ret i1 %and } define i1 @test1b_logical(i1 %a, i1 %b) { ; CHECK-LABEL: @test1b_logical( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[LHS:%.*]] = select i1 [[B:%.*]], i1 [[WC]], i1 false ; CHECK-NEXT: call void @use(i1 [[LHS]]) ; CHECK-NEXT: [[AND:%.*]] = select i1 [[LHS]], i1 [[A:%.*]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %lhs = select i1 %b, i1 %wc, i1 false call void @use(i1 %lhs) %and = select i1 %lhs, i1 %a, i1 false ret i1 %and } ; multiple uses of A, B, WC doesn't change result define i1 @test1c(i1 %a, i1 %b) { ; CHECK-LABEL: @test1c( ; CHECK-NEXT: call void @use(i1 [[A:%.*]]) ; 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: [[AND:%.*]] = and i1 [[LHS]], [[A]] ; CHECK-NEXT: ret i1 [[AND]] ; call void @use(i1 %a) call void @use(i1 %b) %wc = call i1 @llvm.experimental.widenable.condition() call void @use(i1 %wc) %lhs = and i1 %b, %wc %and = and i1 %lhs, %a ret i1 %and } define i1 @test1c_logical(i1 %a, i1 %b) { ; CHECK-LABEL: @test1c_logical( ; CHECK-NEXT: call void @use(i1 [[A:%.*]]) ; 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:%.*]] = select i1 [[B]], i1 [[WC]], i1 false ; CHECK-NEXT: [[AND:%.*]] = select i1 [[LHS]], i1 [[A]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; call void @use(i1 %a) call void @use(i1 %b) %wc = call i1 @llvm.experimental.widenable.condition() call void @use(i1 %wc) %lhs = select i1 %b, i1 %wc, i1 false %and = select i1 %lhs, i1 %a, i1 false ret i1 %and } define i1 @test2(i1 %a, i1 %b) { ; CHECK-LABEL: @test2( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[LHS:%.*]] = and i1 [[WC]], [[B:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i1 [[LHS]], [[A:%.*]] ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %lhs = and i1 %wc, %b %and = and i1 %lhs, %a ret i1 %and } define i1 @test2_logical(i1 %a, i1 %b) { ; CHECK-LABEL: @test2_logical( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[LHS:%.*]] = select i1 [[WC]], i1 [[B:%.*]], i1 false ; CHECK-NEXT: [[AND:%.*]] = select i1 [[LHS]], i1 [[A:%.*]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %lhs = select i1 %wc, i1 %b, i1 false %and = select i1 %lhs, i1 %a, i1 false ret i1 %and } ; To test the rhs side, an instruction on lhs to prevent complexity ; canonicalization reducing to above. define i1 @test3(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @test3( ; 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: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %lhs = and i1 %a, %b %rhs = and i1 %c, %wc %and = and i1 %lhs, %rhs ret i1 %and } define i1 @test3_logical(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @test3_logical( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[LHS:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[LHS]], i1 [[C:%.*]], i1 false ; CHECK-NEXT: [[AND:%.*]] = select i1 [[TMP1]], i1 [[WC]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %lhs = select i1 %a, i1 %b, i1 false %rhs = select i1 %c, i1 %wc, i1 false %and = select i1 %lhs, i1 %rhs, i1 false ret i1 %and } define i1 @test4(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @test4( ; 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: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %lhs = and i1 %a, %b %rhs = and i1 %wc, %c %and = and i1 %lhs, %rhs ret i1 %and } define i1 @test4_logical(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @test4_logical( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[LHS:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[LHS]], i1 [[WC]], i1 false ; CHECK-NEXT: [[AND:%.*]] = select i1 [[TMP1]], i1 [[C:%.*]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %lhs = select i1 %a, i1 %b, i1 false %rhs = select i1 %wc, i1 %c, i1 false %and = select i1 %lhs, i1 %rhs, i1 false ret i1 %and } define i1 @test5(i1 %a, i1 %b) { ; CHECK-LABEL: @test5( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: ret i1 [[WC]] ; %wc = call i1 @llvm.experimental.widenable.condition() %and = and i1 %wc, %wc ret i1 %and } define i1 @test5_logical(i1 %a, i1 %b) { ; CHECK-LABEL: @test5_logical( ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: ret i1 [[WC]] ; %wc = call i1 @llvm.experimental.widenable.condition() %and = select i1 %wc, i1 %wc, i1 false ret i1 %and } define i1 @test6(i1 %a, i1 %b) { ; CHECK-LABEL: @test6( ; 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: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %wc2 = call i1 @llvm.experimental.widenable.condition() %and = and i1 %wc, %wc2 ret i1 %and } define i1 @test6_logical(i1 %a, i1 %b) { ; 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:%.*]] = select i1 [[WC]], i1 [[WC2]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %wc2 = call i1 @llvm.experimental.widenable.condition() %and = select i1 %wc, i1 %wc2, i1 false ret i1 %and } define i1 @test7(i1 %a, i1 %b) { ; CHECK-LABEL: @test7( ; 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: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() call void @use(i1 %wc) %wc2 = call i1 @llvm.experimental.widenable.condition() %and = and i1 %wc, %wc2 ret i1 %and } define i1 @test7_logical(i1 %a, i1 %b) { ; CHECK-LABEL: @test7_logical( ; 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:%.*]] = select i1 [[WC]], i1 [[WC2]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() call void @use(i1 %wc) %wc2 = call i1 @llvm.experimental.widenable.condition() %and = select i1 %wc, i1 %wc2, i1 false ret i1 %and } define i1 @test8(i1 %a, i1 %b) { ; CHECK-LABEL: @test8( ; 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: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %wc2 = call i1 @llvm.experimental.widenable.condition() call void @use(i1 %wc2) %and = and i1 %wc, %wc2 ret i1 %and } define i1 @test8_logical(i1 %a, i1 %b) { ; CHECK-LABEL: @test8_logical( ; 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:%.*]] = select i1 [[WC]], i1 [[WC2]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %wc = call i1 @llvm.experimental.widenable.condition() %wc2 = call i1 @llvm.experimental.widenable.condition() call void @use(i1 %wc2) %and = select i1 %wc, i1 %wc2, i1 false ret i1 %and } declare void @use(i1) declare i1 @llvm.experimental.widenable.condition()