1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --prefix-filecheck-ir-name V 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; https://bugs.llvm.org/show_bug.cgi?id=38446 5 6; Pattern: 7; ~(x ^ y) 8; Should be transformed into: 9; (~x) ^ y 10; or into 11; x ^ (~y) 12 13; While -passes=reassociate does handle this simple pattern, it does not handle 14; the more complicated motivating pattern. 15 16; ============================================================================ ; 17; Basic positive tests 18; ============================================================================ ; 19 20; If the operand is easily-invertible, fold into it. 21declare i1 @gen1() 22 23define i1 @positive_easyinvert(i16 %x, i8 %y) { 24; CHECK-LABEL: @positive_easyinvert( 25; CHECK-NEXT: [[VTMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0 26; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i16 [[X:%.*]], -1 27; CHECK-NEXT: [[VTMP4:%.*]] = xor i1 [[VTMP2]], [[TMP1]] 28; CHECK-NEXT: ret i1 [[VTMP4]] 29; 30 %tmp1 = icmp slt i16 %x, 0 31 %tmp2 = icmp slt i8 %y, 0 32 %tmp3 = xor i1 %tmp2, %tmp1 33 %tmp4 = xor i1 %tmp3, true 34 ret i1 %tmp4 35} 36 37define i1 @positive_easyinvert0(i8 %y) { 38; CHECK-LABEL: @positive_easyinvert0( 39; CHECK-NEXT: [[VTMP1:%.*]] = call i1 @gen1() 40; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[Y:%.*]], -1 41; CHECK-NEXT: [[VTMP4:%.*]] = xor i1 [[TMP1]], [[VTMP1]] 42; CHECK-NEXT: ret i1 [[VTMP4]] 43; 44 %tmp1 = call i1 @gen1() 45 %cond = icmp slt i8 %y, 0 46 %tmp3 = xor i1 %cond, %tmp1 47 %tmp4 = xor i1 %tmp3, true 48 ret i1 %tmp4 49} 50 51define i1 @positive_easyinvert1(i8 %y) { 52; CHECK-LABEL: @positive_easyinvert1( 53; CHECK-NEXT: [[VTMP1:%.*]] = call i1 @gen1() 54; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[Y:%.*]], -1 55; CHECK-NEXT: [[VTMP4:%.*]] = xor i1 [[VTMP1]], [[TMP1]] 56; CHECK-NEXT: ret i1 [[VTMP4]] 57; 58 %tmp1 = call i1 @gen1() 59 %tmp2 = icmp slt i8 %y, 0 60 %tmp3 = xor i1 %tmp1, %tmp2 61 %tmp4 = xor i1 %tmp3, true 62 ret i1 %tmp4 63} 64 65; ============================================================================ ; 66; One-use tests with easily-invertible operand. 67; ============================================================================ ; 68 69declare void @use1(i1) 70 71define i1 @oneuse_easyinvert_0(i8 %y) { 72; CHECK-LABEL: @oneuse_easyinvert_0( 73; CHECK-NEXT: [[VTMP1:%.*]] = call i1 @gen1() 74; CHECK-NEXT: [[VTMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0 75; CHECK-NEXT: call void @use1(i1 [[VTMP2]]) 76; CHECK-NEXT: [[VTMP3:%.*]] = xor i1 [[VTMP1]], [[VTMP2]] 77; CHECK-NEXT: [[VTMP4:%.*]] = xor i1 [[VTMP3]], true 78; CHECK-NEXT: ret i1 [[VTMP4]] 79; 80 %tmp1 = call i1 @gen1() 81 %tmp2 = icmp slt i8 %y, 0 82 call void @use1(i1 %tmp2) 83 %tmp3 = xor i1 %tmp1, %tmp2 84 %tmp4 = xor i1 %tmp3, true 85 ret i1 %tmp4 86} 87 88define i1 @oneuse_easyinvert_1(i8 %y) { 89; CHECK-LABEL: @oneuse_easyinvert_1( 90; CHECK-NEXT: [[VTMP1:%.*]] = call i1 @gen1() 91; CHECK-NEXT: [[VTMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0 92; CHECK-NEXT: [[VTMP3:%.*]] = xor i1 [[VTMP1]], [[VTMP2]] 93; CHECK-NEXT: call void @use1(i1 [[VTMP3]]) 94; CHECK-NEXT: [[VTMP4:%.*]] = xor i1 [[VTMP3]], true 95; CHECK-NEXT: ret i1 [[VTMP4]] 96; 97 %tmp1 = call i1 @gen1() 98 %tmp2 = icmp slt i8 %y, 0 99 %tmp3 = xor i1 %tmp1, %tmp2 100 call void @use1(i1 %tmp3) 101 %tmp4 = xor i1 %tmp3, true 102 ret i1 %tmp4 103} 104 105define i1 @oneuse_easyinvert_2(i8 %y) { 106; CHECK-LABEL: @oneuse_easyinvert_2( 107; CHECK-NEXT: [[VTMP1:%.*]] = call i1 @gen1() 108; CHECK-NEXT: [[VTMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0 109; CHECK-NEXT: call void @use1(i1 [[VTMP2]]) 110; CHECK-NEXT: [[VTMP3:%.*]] = xor i1 [[VTMP1]], [[VTMP2]] 111; CHECK-NEXT: call void @use1(i1 [[VTMP3]]) 112; CHECK-NEXT: [[VTMP4:%.*]] = xor i1 [[VTMP3]], true 113; CHECK-NEXT: ret i1 [[VTMP4]] 114; 115 %tmp1 = call i1 @gen1() 116 %tmp2 = icmp slt i8 %y, 0 117 call void @use1(i1 %tmp2) 118 %tmp3 = xor i1 %tmp1, %tmp2 119 call void @use1(i1 %tmp3) 120 %tmp4 = xor i1 %tmp3, true 121 ret i1 %tmp4 122} 123 124; ============================================================================ ; 125; Negative tests 126; ============================================================================ ; 127 128; Not easily invertible. 129define i32 @negative(i32 %x, i32 %y) { 130; CHECK-LABEL: @negative( 131; CHECK-NEXT: [[VTMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]] 132; CHECK-NEXT: [[VTMP2:%.*]] = xor i32 [[VTMP1]], -1 133; CHECK-NEXT: ret i32 [[VTMP2]] 134; 135 %tmp1 = xor i32 %x, %y 136 %tmp2 = xor i32 %tmp1, -1 137 ret i32 %tmp2 138} 139