1 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64 | FileCheck %s 2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -stop-after machine-combiner -o - | FileCheck %s --check-prefix=DEAD 3 4 ; Verify that integer multiplies are reassociated. The first multiply in 5 ; each test should be independent of the result of the preceding add (lea). 6 7 ; TODO: This test does not actually test i16 machine instruction reassociation 8 ; because the operands are being promoted to i32 types. 9 10 define i16 @reassociate_muls_i16(i16 %x0, i16 %x1, i16 %x2, i16 %x3) { 11 ; CHECK-LABEL: reassociate_muls_i16: 12 ; CHECK: # BB#0: 13 ; CHECK-NEXT: # kill 14 ; CHECK-NEXT: # kill 15 ; CHECK-NEXT: leal (%rdi,%rsi), %eax 16 ; CHECK-NEXT: imull %ecx, %edx 17 ; CHECK-NEXT: imull %edx, %eax 18 ; CHECK-NEXT: # kill 19 ; CHECK-NEXT: retq 20 %t0 = add i16 %x0, %x1 21 %t1 = mul i16 %x2, %t0 22 %t2 = mul i16 %x3, %t1 23 ret i16 %t2 24 } 25 26 define i32 @reassociate_muls_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { 27 ; CHECK-LABEL: reassociate_muls_i32: 28 ; CHECK: # BB#0: 29 ; CHECK-NEXT: # kill 30 ; CHECK-NEXT: # kill 31 ; CHECK-NEXT: leal (%rdi,%rsi), %eax 32 ; CHECK-NEXT: imull %ecx, %edx 33 ; CHECK-NEXT: imull %edx, %eax 34 ; CHECK-NEXT: retq 35 36 ; DEAD: ADD32rr 37 ; DEAD-NEXT: IMUL32rr{{.*}}implicit-def dead %eflags 38 ; DEAD-NEXT: IMUL32rr{{.*}}implicit-def dead %eflags 39 40 %t0 = add i32 %x0, %x1 41 %t1 = mul i32 %x2, %t0 42 %t2 = mul i32 %x3, %t1 43 ret i32 %t2 44 } 45 46 define i64 @reassociate_muls_i64(i64 %x0, i64 %x1, i64 %x2, i64 %x3) { 47 ; CHECK-LABEL: reassociate_muls_i64: 48 ; CHECK: # BB#0: 49 ; CHECK-NEXT: leaq (%rdi,%rsi), %rax 50 ; CHECK-NEXT: imulq %rcx, %rdx 51 ; CHECK-NEXT: imulq %rdx, %rax 52 ; CHECK-NEXT: retq 53 %t0 = add i64 %x0, %x1 54 %t1 = mul i64 %x2, %t0 55 %t2 = mul i64 %x3, %t1 56 ret i64 %t2 57 } 58 59 ; Verify that integer 'ands' are reassociated. The first 'and' in 60 ; each test should be independent of the result of the preceding sub. 61 62 define i8 @reassociate_ands_i8(i8 %x0, i8 %x1, i8 %x2, i8 %x3) { 63 ; CHECK-LABEL: reassociate_ands_i8: 64 ; CHECK: # BB#0: 65 ; CHECK-NEXT: subb %sil, %dil 66 ; CHECK-NEXT: andb %cl, %dl 67 ; CHECK-NEXT: andb %dil, %dl 68 ; CHECK-NEXT: movl %edx, %eax 69 ; CHECK-NEXT: retq 70 %t0 = sub i8 %x0, %x1 71 %t1 = and i8 %x2, %t0 72 %t2 = and i8 %x3, %t1 73 ret i8 %t2 74 } 75 76 ; TODO: No way to test i16? These appear to always get promoted to i32. 77 78 define i32 @reassociate_ands_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { 79 ; CHECK-LABEL: reassociate_ands_i32: 80 ; CHECK: # BB#0: 81 ; CHECK-NEXT: subl %esi, %edi 82 ; CHECK-NEXT: andl %ecx, %edx 83 ; CHECK-NEXT: andl %edi, %edx 84 ; CHECK-NEXT: movl %edx, %eax 85 ; CHECK-NEXT: retq 86 %t0 = sub i32 %x0, %x1 87 %t1 = and i32 %x2, %t0 88 %t2 = and i32 %x3, %t1 89 ret i32 %t2 90 } 91 92 define i64 @reassociate_ands_i64(i64 %x0, i64 %x1, i64 %x2, i64 %x3) { 93 ; CHECK-LABEL: reassociate_ands_i64: 94 ; CHECK: # BB#0: 95 ; CHECK-NEXT: subq %rsi, %rdi 96 ; CHECK-NEXT: andq %rcx, %rdx 97 ; CHECK-NEXT: andq %rdi, %rdx 98 ; CHECK-NEXT: movq %rdx, %rax 99 ; CHECK-NEXT: retq 100 %t0 = sub i64 %x0, %x1 101 %t1 = and i64 %x2, %t0 102 %t2 = and i64 %x3, %t1 103 ret i64 %t2 104 } 105 106 ; Verify that integer 'ors' are reassociated. The first 'or' in 107 ; each test should be independent of the result of the preceding sub. 108 109 define i8 @reassociate_ors_i8(i8 %x0, i8 %x1, i8 %x2, i8 %x3) { 110 ; CHECK-LABEL: reassociate_ors_i8: 111 ; CHECK: # BB#0: 112 ; CHECK-NEXT: subb %sil, %dil 113 ; CHECK-NEXT: orb %cl, %dl 114 ; CHECK-NEXT: orb %dil, %dl 115 ; CHECK-NEXT: movl %edx, %eax 116 ; CHECK-NEXT: retq 117 %t0 = sub i8 %x0, %x1 118 %t1 = or i8 %x2, %t0 119 %t2 = or i8 %x3, %t1 120 ret i8 %t2 121 } 122 123 ; TODO: No way to test i16? These appear to always get promoted to i32. 124 125 define i32 @reassociate_ors_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { 126 ; CHECK-LABEL: reassociate_ors_i32: 127 ; CHECK: # BB#0: 128 ; CHECK-NEXT: subl %esi, %edi 129 ; CHECK-NEXT: orl %ecx, %edx 130 ; CHECK-NEXT: orl %edi, %edx 131 ; CHECK-NEXT: movl %edx, %eax 132 ; CHECK-NEXT: retq 133 %t0 = sub i32 %x0, %x1 134 %t1 = or i32 %x2, %t0 135 %t2 = or i32 %x3, %t1 136 ret i32 %t2 137 } 138 139 define i64 @reassociate_ors_i64(i64 %x0, i64 %x1, i64 %x2, i64 %x3) { 140 ; CHECK-LABEL: reassociate_ors_i64: 141 ; CHECK: # BB#0: 142 ; CHECK-NEXT: subq %rsi, %rdi 143 ; CHECK-NEXT: orq %rcx, %rdx 144 ; CHECK-NEXT: orq %rdi, %rdx 145 ; CHECK-NEXT: movq %rdx, %rax 146 ; CHECK-NEXT: retq 147 %t0 = sub i64 %x0, %x1 148 %t1 = or i64 %x2, %t0 149 %t2 = or i64 %x3, %t1 150 ret i64 %t2 151 } 152 153 ; Verify that integer 'xors' are reassociated. The first 'xor' in 154 ; each test should be independent of the result of the preceding sub. 155 156 define i8 @reassociate_xors_i8(i8 %x0, i8 %x1, i8 %x2, i8 %x3) { 157 ; CHECK-LABEL: reassociate_xors_i8: 158 ; CHECK: # BB#0: 159 ; CHECK-NEXT: subb %sil, %dil 160 ; CHECK-NEXT: xorb %cl, %dl 161 ; CHECK-NEXT: xorb %dil, %dl 162 ; CHECK-NEXT: movl %edx, %eax 163 ; CHECK-NEXT: retq 164 %t0 = sub i8 %x0, %x1 165 %t1 = xor i8 %x2, %t0 166 %t2 = xor i8 %x3, %t1 167 ret i8 %t2 168 } 169 170 ; TODO: No way to test i16? These appear to always get promoted to i32. 171 172 define i32 @reassociate_xors_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { 173 ; CHECK-LABEL: reassociate_xors_i32: 174 ; CHECK: # BB#0: 175 ; CHECK-NEXT: subl %esi, %edi 176 ; CHECK-NEXT: xorl %ecx, %edx 177 ; CHECK-NEXT: xorl %edi, %edx 178 ; CHECK-NEXT: movl %edx, %eax 179 ; CHECK-NEXT: retq 180 %t0 = sub i32 %x0, %x1 181 %t1 = xor i32 %x2, %t0 182 %t2 = xor i32 %x3, %t1 183 ret i32 %t2 184 } 185 186 define i64 @reassociate_xors_i64(i64 %x0, i64 %x1, i64 %x2, i64 %x3) { 187 ; CHECK-LABEL: reassociate_xors_i64: 188 ; CHECK: # BB#0: 189 ; CHECK-NEXT: subq %rsi, %rdi 190 ; CHECK-NEXT: xorq %rcx, %rdx 191 ; CHECK-NEXT: xorq %rdi, %rdx 192 ; CHECK-NEXT: movq %rdx, %rax 193 ; CHECK-NEXT: retq 194 %t0 = sub i64 %x0, %x1 195 %t1 = xor i64 %x2, %t0 196 %t2 = xor i64 %x3, %t1 197 ret i64 %t2 198 } 199 200