Browse Source

* use bzhi only (if at all) for in_and_assign_x_y and not other in_*_x_y operations, resolves #40016

florian 2 years ago
parent
commit
96d4bd19ac
2 changed files with 40 additions and 1 deletions
  1. 1 1
      compiler/x86/nx86inl.pas
  2. 39 0
      tests/webtbs/tw40016.pp

+ 1 - 1
compiler/x86/nx86inl.pas

@@ -636,7 +636,7 @@ implementation
              opsize := def_cgsize(loadnode.resultdef);
 
              { BMI2 optimisations }
-             if (CPUX86_HAS_BMI2 in cpu_capabilities[current_settings.cputype]) then
+             if (CPUX86_HAS_BMI2 in cpu_capabilities[current_settings.cputype]) and (inlinenumber=in_and_assign_x_y) then
                begin
                  { If the second operand is "((1 shl y) - 1)", we can turn it
                    into a BZHI operator instead }

+ 39 - 0
tests/webtbs/tw40016.pp

@@ -0,0 +1,39 @@
+{ %CPU=x86_64 }
+{ %opt=-Cpcoreavx2 -O4 }
+uses
+  cpu;
+
+procedure Verify(const op: string; got, expected: SizeUint);
+begin
+	write('%10101010 ' + op + ' %111 = %' + BinStr(got, 1 + BsrQWord(got or 1)));
+	if got = expected then
+		writeln(' - ok')
+	else
+	  begin
+		writeln(' - FAIL, must be %' + BinStr(expected, 1 + BsrQWord(expected or 1)));
+		halt(1);
+	  end;
+end;
+
+var
+	b, nbits: SizeUint;
+
+
+begin
+    if BMI2Support then
+	  begin
+		nbits := 3 + random(0);
+
+		b := %10101010 + random(0);
+		b := b or (SizeUint(1) shl nbits - 1);
+		Verify('or', b, %10101111);
+
+		b := %10101010 + random(0);
+		b := b xor (SizeUint(1) shl nbits - 1);
+		Verify('xor', b, %10101101);
+
+		b := %10101010 + random(0);
+		b := b and (SizeUint(1) shl nbits - 1);
+		Verify('and', b, %10);
+	  end;
+end.