; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s define i1 @test_switch_with_xor(i32 %x) { ; CHECK-LABEL: define i1 @test_switch_with_xor( ; CHECK-SAME: i32 [[X:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: switch i32 [[X]], label %[[SW_DEFAULT:.*]] [ ; CHECK-NEXT: i32 3, label %[[SW_BB:.*]] ; CHECK-NEXT: i32 0, label %[[SW_BB]] ; CHECK-NEXT: i32 1, label %[[SW_BB]] ; CHECK-NEXT: ] ; CHECK: [[SW_BB]]: ; CHECK-NEXT: ret i1 true ; CHECK: [[SW_DEFAULT]]: ; CHECK-NEXT: ret i1 false ; entry: %xor = xor i32 %x, 2 switch i32 %xor, label %sw.default [ i32 1, label %sw.bb i32 2, label %sw.bb i32 3, label %sw.bb ] sw.bb: ret i1 true sw.default: ret i1 false } ; Negative tests. define i1 @test_switch_with_xor_nonconstant_ops(i32 %x, i32 %y) { ; CHECK-LABEL: define i1 @test_switch_with_xor_nonconstant_ops( ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]] ; CHECK-NEXT: switch i32 [[XOR]], label %[[SW_DEFAULT:.*]] [ ; CHECK-NEXT: i32 1, label %[[SW_BB:.*]] ; CHECK-NEXT: i32 2, label %[[SW_BB]] ; CHECK-NEXT: i32 3, label %[[SW_BB]] ; CHECK-NEXT: ] ; CHECK: [[SW_BB]]: ; CHECK-NEXT: ret i1 true ; CHECK: [[SW_DEFAULT]]: ; CHECK-NEXT: ret i1 false ; entry: %xor = xor i32 %x, %y switch i32 %xor, label %sw.default [ i32 1, label %sw.bb i32 2, label %sw.bb i32 3, label %sw.bb ] sw.bb: ret i1 true sw.default: ret i1 false } define i1 @test_switch_with_xor_condition_multiple_uses(i32 %x) { ; CHECK-LABEL: define i1 @test_switch_with_xor_condition_multiple_uses( ; CHECK-SAME: i32 [[X:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], 2 ; CHECK-NEXT: call void @opaque(i32 [[XOR]]) ; CHECK-NEXT: switch i32 [[XOR]], label %[[SW_DEFAULT:.*]] [ ; CHECK-NEXT: i32 1, label %[[SW_BB:.*]] ; CHECK-NEXT: i32 2, label %[[SW_BB]] ; CHECK-NEXT: i32 3, label %[[SW_BB]] ; CHECK-NEXT: ] ; CHECK: [[SW_BB]]: ; CHECK-NEXT: ret i1 true ; CHECK: [[SW_DEFAULT]]: ; CHECK-NEXT: ret i1 false ; entry: %xor = xor i32 %x, 2 call void @opaque(i32 %xor) switch i32 %xor, label %sw.default [ i32 1, label %sw.bb i32 2, label %sw.bb i32 3, label %sw.bb ] sw.bb: ret i1 true sw.default: ret i1 false } define i1 @test_switch_with_xor_by_int_min(i64 %x) { ; CHECK-LABEL: define i1 @test_switch_with_xor_by_int_min( ; CHECK-SAME: i64 [[X:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[X]], -9223372036854775808 ; CHECK-NEXT: switch i64 [[XOR]], label %[[SW_DEFAULT:.*]] [ ; CHECK-NEXT: i64 1, label %[[SW_BB:.*]] ; CHECK-NEXT: i64 2, label %[[SW_BB]] ; CHECK-NEXT: i64 3, label %[[SW_BB]] ; CHECK-NEXT: ] ; CHECK: [[SW_BB]]: ; CHECK-NEXT: ret i1 true ; CHECK: [[SW_DEFAULT]]: ; CHECK-NEXT: ret i1 false ; entry: %xor = xor i64 %x, -9223372036854775808 switch i64 %xor, label %sw.default [ i64 1, label %sw.bb i64 2, label %sw.bb i64 3, label %sw.bb ] sw.bb: ; preds = %entry, %entry, %entry ret i1 true sw.default: ; preds = %entry ret i1 false } define i1 @test_switch_with_xor_by_int_max(i64 %x) { ; CHECK-LABEL: define i1 @test_switch_with_xor_by_int_max( ; CHECK-SAME: i64 [[X:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[XOR:%.*]] = xor i64 [[X]], 9223372036854775807 ; CHECK-NEXT: switch i64 [[XOR]], label %[[SW_DEFAULT:.*]] [ ; CHECK-NEXT: i64 1, label %[[SW_BB:.*]] ; CHECK-NEXT: i64 2, label %[[SW_BB]] ; CHECK-NEXT: i64 3, label %[[SW_BB]] ; CHECK-NEXT: ] ; CHECK: [[SW_BB]]: ; CHECK-NEXT: ret i1 true ; CHECK: [[SW_DEFAULT]]: ; CHECK-NEXT: ret i1 false ; entry: %xor = xor i64 %x, 9223372036854775807 switch i64 %xor, label %sw.default [ i64 1, label %sw.bb i64 2, label %sw.bb i64 3, label %sw.bb ] sw.bb: ; preds = %entry, %entry, %entry ret i1 true sw.default: ; preds = %entry ret i1 false } declare void @opaque(i32)