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 19 // A dummy value to defeat inlining of these routines. 20 static boolean doThrow = false; 21 22 public static void assertIntEquals(int expected, int result) { 23 if (expected != result) { 24 throw new Error("Expected: " + expected + ", found: " + result); 25 } 26 } 27 28 public static void assertLongEquals(long expected, long result) { 29 if (expected != result) { 30 throw new Error("Expected: " + expected + ", found: " + result); 31 } 32 } 33 34 /** 35 * Test merging of `NOT+AND` into `BIC`. 36 */ 37 38 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (before) 39 /// CHECK: <<Base:i\d+>> ParameterValue 40 /// CHECK: <<Mask:i\d+>> ParameterValue 41 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 42 /// CHECK: <<Op:i\d+>> And [<<Base>>,<<Not>>] 43 /// CHECK: Return [<<Op>>] 44 45 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (after) 46 /// CHECK: <<Base:i\d+>> ParameterValue 47 /// CHECK: <<Mask:i\d+>> ParameterValue 48 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:And 49 /// CHECK: Return [<<NegOp>>] 50 51 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (after) 52 /// CHECK-NOT: Not 53 /// CHECK-NOT: And 54 55 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) disassembly (after) 56 /// CHECK: bic w{{\d+}}, w{{\d+}}, w{{\d+}} 57 58 59 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (before) 60 /// CHECK: <<Base:i\d+>> ParameterValue 61 /// CHECK: <<Mask:i\d+>> ParameterValue 62 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 63 /// CHECK: <<Op:i\d+>> And [<<Base>>,<<Not>>] 64 /// CHECK: Return [<<Op>>] 65 66 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (after) 67 /// CHECK: <<Base:i\d+>> ParameterValue 68 /// CHECK: <<Mask:i\d+>> ParameterValue 69 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:And 70 /// CHECK: Return [<<NegOp>>] 71 72 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (after) 73 /// CHECK-NOT: Not 74 /// CHECK-NOT: And 75 76 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) disassembly (after) 77 /// CHECK: bic r{{\d+}}, r{{\d+}}, r{{\d+}} 78 79 public static int $opt$noinline$notAnd(int base, int mask) { 80 if (doThrow) throw new Error(); 81 return base & ~mask; 82 } 83 84 /** 85 * Test merging of `NOT+ORR` into `ORN`. 86 */ 87 88 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (before) 89 /// CHECK: <<Base:j\d+>> ParameterValue 90 /// CHECK: <<Mask:j\d+>> ParameterValue 91 /// CHECK: <<Not:j\d+>> Not [<<Mask>>] 92 /// CHECK: <<Op:j\d+>> Or [<<Base>>,<<Not>>] 93 /// CHECK: Return [<<Op>>] 94 95 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (after) 96 /// CHECK: <<Base:j\d+>> ParameterValue 97 /// CHECK: <<Mask:j\d+>> ParameterValue 98 /// CHECK: <<NegOp:j\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Or 99 /// CHECK: Return [<<NegOp>>] 100 101 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (after) 102 /// CHECK-NOT: Not 103 /// CHECK-NOT: Or 104 105 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) disassembly (after) 106 /// CHECK: orn x{{\d+}}, x{{\d+}}, x{{\d+}} 107 108 109 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (before) 110 /// CHECK: <<Base:j\d+>> ParameterValue 111 /// CHECK: <<Mask:j\d+>> ParameterValue 112 /// CHECK: <<Not:j\d+>> Not [<<Mask>>] 113 /// CHECK: <<Op:j\d+>> Or [<<Base>>,<<Not>>] 114 /// CHECK: Return [<<Op>>] 115 116 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (after) 117 /// CHECK: <<Base:j\d+>> ParameterValue 118 /// CHECK: <<Mask:j\d+>> ParameterValue 119 /// CHECK: <<NegOp:j\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Or 120 /// CHECK: Return [<<NegOp>>] 121 122 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (after) 123 /// CHECK-NOT: Not 124 /// CHECK-NOT: Or 125 126 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) disassembly (after) 127 /// CHECK: orn r{{\d+}}, r{{\d+}}, r{{\d+}} 128 129 public static long $opt$noinline$notOr(long base, long mask) { 130 if (doThrow) throw new Error(); 131 return base | ~mask; 132 } 133 134 /** 135 * Test merging of `NOT+EOR` into `EON`. 136 */ 137 138 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (before) 139 /// CHECK: <<Base:i\d+>> ParameterValue 140 /// CHECK: <<Mask:i\d+>> ParameterValue 141 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 142 /// CHECK: <<Op:i\d+>> Xor [<<Base>>,<<Not>>] 143 /// CHECK: Return [<<Op>>] 144 145 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (after) 146 /// CHECK: <<Base:i\d+>> ParameterValue 147 /// CHECK: <<Mask:i\d+>> ParameterValue 148 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Xor 149 /// CHECK: Return [<<NegOp>>] 150 151 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (after) 152 /// CHECK-NOT: Not 153 /// CHECK-NOT: Xor 154 155 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) disassembly (after) 156 /// CHECK: eon w{{\d+}}, w{{\d+}}, w{{\d+}} 157 158 159 /// CHECK-START-ARM: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (before) 160 /// CHECK: <<Base:i\d+>> ParameterValue 161 /// CHECK: <<Mask:i\d+>> ParameterValue 162 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 163 /// CHECK: <<Op:i\d+>> Xor [<<Base>>,<<Not>>] 164 /// CHECK: Return [<<Op>>] 165 166 /// CHECK-START-ARM: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (after) 167 /// CHECK: <<Base:i\d+>> ParameterValue 168 /// CHECK: <<Mask:i\d+>> ParameterValue 169 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 170 /// CHECK: <<Op:i\d+>> Xor [<<Base>>,<<Not>>] 171 /// CHECK: Return [<<Op>>] 172 173 /// CHECK-START-ARM: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (after) 174 /// CHECK-NOT: BitwiseNegatedRight 175 176 public static int $opt$noinline$notXor(int base, int mask) { 177 if (doThrow) throw new Error(); 178 return base ^ ~mask; 179 } 180 181 /** 182 * Check that transformation is done when the argument is a constant. 183 */ 184 185 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm64 (before) 186 /// CHECK: <<Base:i\d+>> ParameterValue 187 /// CHECK: <<Constant:i\d+>> IntConstant 188 /// CHECK: <<Not:i\d+>> Not [<<Base>>] 189 /// CHECK: <<Op:i\d+>> And [<<Not>>,<<Constant>>] 190 /// CHECK: Return [<<Op>>] 191 192 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm64 (after) 193 /// CHECK: <<Base:i\d+>> ParameterValue 194 /// CHECK: <<Constant:i\d+>> IntConstant 195 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And 196 /// CHECK: Return [<<NegOp>>] 197 198 199 /// CHECK-START-ARM: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm (before) 200 /// CHECK: <<Base:i\d+>> ParameterValue 201 /// CHECK: <<Constant:i\d+>> IntConstant 202 /// CHECK: <<Not:i\d+>> Not [<<Base>>] 203 /// CHECK: <<Op:i\d+>> And [<<Not>>,<<Constant>>] 204 /// CHECK: Return [<<Op>>] 205 206 /// CHECK-START-ARM: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm (after) 207 /// CHECK: <<Base:i\d+>> ParameterValue 208 /// CHECK: <<Constant:i\d+>> IntConstant 209 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And 210 /// CHECK: Return [<<NegOp>>] 211 212 public static int $opt$noinline$notAndConstant(int mask) { 213 if (doThrow) throw new Error(); 214 return 0xf & ~mask; 215 } 216 217 /** 218 * Check that no transformation is done when Not has multiple uses. 219 */ 220 221 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (before) 222 /// CHECK: <<Base:i\d+>> ParameterValue 223 /// CHECK: <<Mask:i\d+>> ParameterValue 224 /// CHECK: <<One:i\d+>> IntConstant 225 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 226 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>] 227 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>] 228 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>] 229 /// CHECK: Return [<<Add>>] 230 231 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (after) 232 /// CHECK: <<Base:i\d+>> ParameterValue 233 /// CHECK: <<Mask:i\d+>> ParameterValue 234 /// CHECK: <<One:i\d+>> IntConstant 235 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 236 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>] 237 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>] 238 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>] 239 /// CHECK: Return [<<Add>>] 240 241 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (after) 242 /// CHECK-NOT: BitwiseNegatedRight 243 244 245 /// CHECK-START-ARM: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (before) 246 /// CHECK: <<Base:i\d+>> ParameterValue 247 /// CHECK: <<Mask:i\d+>> ParameterValue 248 /// CHECK: <<One:i\d+>> IntConstant 249 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 250 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>] 251 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>] 252 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>] 253 /// CHECK: Return [<<Add>>] 254 255 /// CHECK-START-ARM: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (after) 256 /// CHECK: <<Base:i\d+>> ParameterValue 257 /// CHECK: <<Mask:i\d+>> ParameterValue 258 /// CHECK: <<One:i\d+>> IntConstant 259 /// CHECK: <<Not:i\d+>> Not [<<Mask>>] 260 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>] 261 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>] 262 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>] 263 /// CHECK: Return [<<Add>>] 264 265 /// CHECK-START-ARM: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (after) 266 /// CHECK-NOT: BitwiseNegatedRight 267 268 public static int $opt$noinline$notAndMultipleUses(int base, int mask) { 269 if (doThrow) throw new Error(); 270 int tmp = ~mask; 271 return (tmp & 0x1) + (base & tmp); 272 } 273 274 /** 275 * Check that no transformation is done when both inputs are Not's. 276 */ 277 278 // We don't check the instructions before the pass, since if De Morgan's laws 279 // have been applied then Not/Not/Or is replaced by And/Not. 280 281 /// CHECK-START-ARM64: int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_arm64 (after) 282 /// CHECK-NOT: BitwiseNegatedRight 283 284 /// CHECK-START-ARM: int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_arm (after) 285 /// CHECK-NOT: BitwiseNegatedRight 286 287 public static int $opt$noinline$deMorganOr(int a, int b) { 288 if (doThrow) throw new Error(); 289 return ~a | ~b; 290 } 291 292 public static void main(String[] args) { 293 assertIntEquals(0xe, $opt$noinline$notAnd(0xf, 0x1)); 294 assertLongEquals(~0x0, $opt$noinline$notOr(0xf, 0x1)); 295 assertIntEquals(~0xe, $opt$noinline$notXor(0xf, 0x1)); 296 assertIntEquals(0xe, $opt$noinline$notAndConstant(0x1)); 297 assertIntEquals(0xe, $opt$noinline$notAndMultipleUses(0xf, 0x1)); 298 assertIntEquals(~0x1, $opt$noinline$deMorganOr(0x3, 0x1)); 299 } 300 } 301