1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2 ; RUN: opt < %s -instcombine -S | FileCheck %s 3 4 ; PR22723: Recognize De Morgan's Laws when obfuscated by zexts. 5 6 define i32 @demorgan_or(i1 %X, i1 %Y) { 7 ; CHECK-LABEL: @demorgan_or( 8 ; CHECK-NEXT: [[OR_DEMORGAN:%.*]] = and i1 %X, %Y 9 ; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[OR_DEMORGAN]] to i32 10 ; CHECK-NEXT: [[OR:%.*]] = xor i32 [[TMP1]], 1 11 ; CHECK-NEXT: ret i32 [[OR]] 12 ; 13 %zextX = zext i1 %X to i32 14 %zextY = zext i1 %Y to i32 15 %notX = xor i32 %zextX, 1 16 %notY = xor i32 %zextY, 1 17 %or = or i32 %notX, %notY 18 ret i32 %or 19 } 20 21 define i32 @demorgan_and(i1 %X, i1 %Y) { 22 ; CHECK-LABEL: @demorgan_and( 23 ; CHECK-NEXT: [[AND_DEMORGAN:%.*]] = or i1 %X, %Y 24 ; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[AND_DEMORGAN]] to i32 25 ; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], 1 26 ; CHECK-NEXT: ret i32 [[AND]] 27 ; 28 %zextX = zext i1 %X to i32 29 %zextY = zext i1 %Y to i32 30 %notX = xor i32 %zextX, 1 31 %notY = xor i32 %zextY, 1 32 %and = and i32 %notX, %notY 33 ret i32 %and 34 } 35 36 ; FIXME: Vectors should get the same transform. 37 38 define <2 x i32> @demorgan_or_vec(<2 x i1> %X, <2 x i1> %Y) { 39 ; CHECK-LABEL: @demorgan_or_vec( 40 ; CHECK-NEXT: [[ZEXTX:%.*]] = zext <2 x i1> %X to <2 x i32> 41 ; CHECK-NEXT: [[ZEXTY:%.*]] = zext <2 x i1> %Y to <2 x i32> 42 ; CHECK-NEXT: [[NOTX:%.*]] = xor <2 x i32> [[ZEXTX]], <i32 1, i32 1> 43 ; CHECK-NEXT: [[NOTY:%.*]] = xor <2 x i32> [[ZEXTY]], <i32 1, i32 1> 44 ; CHECK-NEXT: [[OR:%.*]] = or <2 x i32> [[NOTX]], [[NOTY]] 45 ; CHECK-NEXT: ret <2 x i32> [[OR]] 46 ; 47 %zextX = zext <2 x i1> %X to <2 x i32> 48 %zextY = zext <2 x i1> %Y to <2 x i32> 49 %notX = xor <2 x i32> %zextX, <i32 1, i32 1> 50 %notY = xor <2 x i32> %zextY, <i32 1, i32 1> 51 %or = or <2 x i32> %notX, %notY 52 ret <2 x i32> %or 53 } 54 55 define <2 x i32> @demorgan_and_vec(<2 x i1> %X, <2 x i1> %Y) { 56 ; CHECK-LABEL: @demorgan_and_vec( 57 ; CHECK-NEXT: [[ZEXTX:%.*]] = zext <2 x i1> %X to <2 x i32> 58 ; CHECK-NEXT: [[ZEXTY:%.*]] = zext <2 x i1> %Y to <2 x i32> 59 ; CHECK-NEXT: [[NOTX:%.*]] = xor <2 x i32> [[ZEXTX]], <i32 1, i32 1> 60 ; CHECK-NEXT: [[NOTY:%.*]] = xor <2 x i32> [[ZEXTY]], <i32 1, i32 1> 61 ; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[NOTX]], [[NOTY]] 62 ; CHECK-NEXT: ret <2 x i32> [[AND]] 63 ; 64 %zextX = zext <2 x i1> %X to <2 x i32> 65 %zextY = zext <2 x i1> %Y to <2 x i32> 66 %notX = xor <2 x i32> %zextX, <i32 1, i32 1> 67 %notY = xor <2 x i32> %zextY, <i32 1, i32 1> 68 %and = and <2 x i32> %notX, %notY 69 ret <2 x i32> %and 70 } 71 72 ; FIXME: If the xor was canonicalized to a 'not', then this would simplify. 73 74 define i32 @PR28476(i32 %x, i32 %y) { 75 ; CHECK-LABEL: @PR28476( 76 ; CHECK-NEXT: [[CMP0:%.*]] = icmp ne i32 %x, 0 77 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 %y, 0 78 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP0]], [[CMP1]] 79 ; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[AND]] to i32 80 ; CHECK-NEXT: [[COND:%.*]] = xor i32 [[ZEXT]], 1 81 ; CHECK-NEXT: ret i32 [[COND]] 82 ; 83 %cmp0 = icmp ne i32 %x, 0 84 %cmp1 = icmp ne i32 %y, 0 85 %and = and i1 %cmp0, %cmp1 86 %zext = zext i1 %and to i32 87 %cond = xor i32 %zext, 1 88 ret i32 %cond 89 } 90 91