1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 public class Main { 18 assertIntEquals(int expected, int result)19 public static void assertIntEquals(int expected, int result) { 20 if (expected != result) { 21 throw new Error("Expected: " + expected + ", found: " + result); 22 } 23 } 24 assertLongEquals(long expected, long result)25 public static void assertLongEquals(long expected, long result) { 26 if (expected != result) { 27 throw new Error("Expected: " + expected + ", found: " + result); 28 } 29 } 30 31 /** 32 * Test merging of `NOT+AND` into `BIC`. 33 */ 34 35 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (before) 36 /// CHECK: <<Base:i\d+>> ParameterValue 37 /// CHECK: <<Mask:i\d+>> ParameterValue 38 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 39 /// CHECK: <<Op:i\d+>> And [<<Base>>,<<Not>>] 40 /// CHECK: Return [<<Op>>] 41 42 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (after) 43 /// CHECK: <<Base:i\d+>> ParameterValue 44 /// CHECK: <<Mask:i\d+>> ParameterValue 45 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:And 46 /// CHECK: Return [<<NegOp>>] 47 48 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (after) 49 /// CHECK-NOT: Not 50 /// CHECK-NOT: And 51 52 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) disassembly (after) 53 /// CHECK: bic w{{\d+}}, w{{\d+}}, w{{\d+}} 54 55 56 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (before) 57 /// CHECK: <<Base:i\d+>> ParameterValue 58 /// CHECK: <<Mask:i\d+>> ParameterValue 59 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 60 /// CHECK: <<Op:i\d+>> And [<<Base>>,<<Not>>] 61 /// CHECK: Return [<<Op>>] 62 63 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (after) 64 /// CHECK: <<Base:i\d+>> ParameterValue 65 /// CHECK: <<Mask:i\d+>> ParameterValue 66 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:And 67 /// CHECK: Return [<<NegOp>>] 68 69 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (after) 70 /// CHECK-NOT: Not 71 /// CHECK-NOT: And 72 73 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) disassembly (after) 74 /// CHECK: bic r{{\d+}}, r{{\d+}}, r{{\d+}} 75 $opt$noinline$notAnd(int base, int mask)76 public static int $opt$noinline$notAnd(int base, int mask) { 77 return base & ~mask; 78 } 79 80 /** 81 * Test merging of `NOT+ORR` into `ORN`. 82 */ 83 84 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (before) 85 /// CHECK: <<Base:j\d+>> ParameterValue 86 /// CHECK: <<Mask:j\d+>> ParameterValue 87 /// CHECK: <<Not:j\d+>> Not [<<Mask>>] 88 /// CHECK: <<Op:j\d+>> Or [<<Base>>,<<Not>>] 89 /// CHECK: Return [<<Op>>] 90 91 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (after) 92 /// CHECK: <<Base:j\d+>> ParameterValue 93 /// CHECK: <<Mask:j\d+>> ParameterValue 94 /// CHECK: <<NegOp:j\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Or 95 /// CHECK: Return [<<NegOp>>] 96 97 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (after) 98 /// CHECK-NOT: Not 99 /// CHECK-NOT: Or 100 101 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) disassembly (after) 102 /// CHECK: orn x{{\d+}}, x{{\d+}}, x{{\d+}} 103 104 105 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (before) 106 /// CHECK: <<Base:j\d+>> ParameterValue 107 /// CHECK: <<Mask:j\d+>> ParameterValue 108 /// CHECK: <<Not:j\d+>> Not [<<Mask>>] 109 /// CHECK: <<Op:j\d+>> Or [<<Base>>,<<Not>>] 110 /// CHECK: Return [<<Op>>] 111 112 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (after) 113 /// CHECK: <<Base:j\d+>> ParameterValue 114 /// CHECK: <<Mask:j\d+>> ParameterValue 115 /// CHECK: <<NegOp:j\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Or 116 /// CHECK: Return [<<NegOp>>] 117 118 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (after) 119 /// CHECK-NOT: Not 120 /// CHECK-NOT: Or 121 122 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) disassembly (after) 123 /// CHECK: orn r{{\d+}}, r{{\d+}}, r{{\d+}} 124 $opt$noinline$notOr(long base, long mask)125 public static long $opt$noinline$notOr(long base, long mask) { 126 return base | ~mask; 127 } 128 129 /** 130 * Test merging of `NOT+EOR` into `EON`. 131 */ 132 133 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (before) 134 /// CHECK: <<Base:i\d+>> ParameterValue 135 /// CHECK: <<Mask:i\d+>> ParameterValue 136 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 137 /// CHECK: <<Op:i\d+>> Xor [<<Base>>,<<Not>>] 138 /// CHECK: Return [<<Op>>] 139 140 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (after) 141 /// CHECK: <<Base:i\d+>> ParameterValue 142 /// CHECK: <<Mask:i\d+>> ParameterValue 143 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Xor 144 /// CHECK: Return [<<NegOp>>] 145 146 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (after) 147 /// CHECK-NOT: Not 148 /// CHECK-NOT: Xor 149 150 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) disassembly (after) 151 /// CHECK: eon w{{\d+}}, w{{\d+}}, w{{\d+}} 152 153 154 /// CHECK-START-ARM: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (before) 155 /// CHECK: <<Base:i\d+>> ParameterValue 156 /// CHECK: <<Mask:i\d+>> ParameterValue 157 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 158 /// CHECK: <<Op:i\d+>> Xor [<<Base>>,<<Not>>] 159 /// CHECK: Return [<<Op>>] 160 161 /// CHECK-START-ARM: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (after) 162 /// CHECK: <<Base:i\d+>> ParameterValue 163 /// CHECK: <<Mask:i\d+>> ParameterValue 164 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 165 /// CHECK: <<Op:i\d+>> Xor [<<Base>>,<<Not>>] 166 /// CHECK: Return [<<Op>>] 167 168 /// CHECK-START-ARM: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (after) 169 /// CHECK-NOT: BitwiseNegatedRight 170 $opt$noinline$notXor(int base, int mask)171 public static int $opt$noinline$notXor(int base, int mask) { 172 return base ^ ~mask; 173 } 174 175 /** 176 * Check that transformation is done when the argument is a constant. 177 */ 178 179 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm64 (before) 180 /// CHECK: <<Base:i\d+>> ParameterValue 181 /// CHECK: <<Constant:i\d+>> IntConstant 182 /// CHECK: <<Not:i\d+>> Not [<<Base>>] 183 /// CHECK: <<Op:i\d+>> And [<<Not>>,<<Constant>>] 184 /// CHECK: Return [<<Op>>] 185 186 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm64 (after) 187 /// CHECK: <<Base:i\d+>> ParameterValue 188 /// CHECK: <<Constant:i\d+>> IntConstant 189 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And 190 /// CHECK: Return [<<NegOp>>] 191 192 193 /// CHECK-START-ARM: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm (before) 194 /// CHECK: <<Base:i\d+>> ParameterValue 195 /// CHECK: <<Constant:i\d+>> IntConstant 196 /// CHECK: <<Not:i\d+>> Not [<<Base>>] 197 /// CHECK: <<Op:i\d+>> And [<<Not>>,<<Constant>>] 198 /// CHECK: Return [<<Op>>] 199 200 /// CHECK-START-ARM: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm (after) 201 /// CHECK: <<Base:i\d+>> ParameterValue 202 /// CHECK: <<Constant:i\d+>> IntConstant 203 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And 204 /// CHECK: Return [<<NegOp>>] 205 $opt$noinline$notAndConstant(int mask)206 public static int $opt$noinline$notAndConstant(int mask) { 207 return 0xf & ~mask; 208 } 209 210 /** 211 * Check that no transformation is done when Not has multiple uses. 212 */ 213 214 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (before) 215 /// CHECK: <<Base:i\d+>> ParameterValue 216 /// CHECK: <<Mask:i\d+>> ParameterValue 217 /// CHECK: <<One:i\d+>> IntConstant 218 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 219 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>] 220 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>] 221 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>] 222 /// CHECK: Return [<<Add>>] 223 224 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (after) 225 /// CHECK: <<Base:i\d+>> ParameterValue 226 /// CHECK: <<Mask:i\d+>> ParameterValue 227 /// CHECK: <<One:i\d+>> IntConstant 228 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 229 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>] 230 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>] 231 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>] 232 /// CHECK: Return [<<Add>>] 233 234 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (after) 235 /// CHECK-NOT: BitwiseNegatedRight 236 237 238 /// CHECK-START-ARM: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (before) 239 /// CHECK: <<Base:i\d+>> ParameterValue 240 /// CHECK: <<Mask:i\d+>> ParameterValue 241 /// CHECK: <<One:i\d+>> IntConstant 242 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 243 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>] 244 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>] 245 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>] 246 /// CHECK: Return [<<Add>>] 247 248 /// CHECK-START-ARM: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (after) 249 /// CHECK: <<Base:i\d+>> ParameterValue 250 /// CHECK: <<Mask:i\d+>> ParameterValue 251 /// CHECK: <<One:i\d+>> IntConstant 252 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 253 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>] 254 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>] 255 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>] 256 /// CHECK: Return [<<Add>>] 257 258 /// CHECK-START-ARM: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (after) 259 /// CHECK-NOT: BitwiseNegatedRight 260 $opt$noinline$notAndMultipleUses(int base, int mask)261 public static int $opt$noinline$notAndMultipleUses(int base, int mask) { 262 int tmp = ~mask; 263 return (tmp & 0x1) + (base & tmp); 264 } 265 266 /** 267 * Check that no transformation is done when both inputs are Not's. 268 */ 269 270 // We don't check the instructions before the pass, since if De Morgan's laws 271 // have been applied then Not/Not/Or is replaced by And/Not. 272 273 /// CHECK-START-ARM64: int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_arm64 (after) 274 /// CHECK-NOT: BitwiseNegatedRight 275 276 /// CHECK-START-ARM: int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_arm (after) 277 /// CHECK-NOT: BitwiseNegatedRight 278 $opt$noinline$deMorganOr(int a, int b)279 public static int $opt$noinline$deMorganOr(int a, int b) { 280 return ~a | ~b; 281 } 282 main(String[] args)283 public static void main(String[] args) { 284 assertIntEquals(0xe, $opt$noinline$notAnd(0xf, 0x1)); 285 assertLongEquals(~0x0, $opt$noinline$notOr(0xf, 0x1)); 286 assertIntEquals(~0xe, $opt$noinline$notXor(0xf, 0x1)); 287 assertIntEquals(0xe, $opt$noinline$notAndConstant(0x1)); 288 assertIntEquals(0xe, $opt$noinline$notAndMultipleUses(0xf, 0x1)); 289 assertIntEquals(~0x1, $opt$noinline$deMorganOr(0x3, 0x1)); 290 } 291 } 292