Many (most? all?) assemblers (and really the 32-bit ABIs) do not handle
lwa and ld properly. Those instructions have a 14-bit offset field, and
the low two bits of the instruction are the extended opcode. But the
32-bit toolchains use a 16-bit offset relocation, clobbering the low
two bits. See PR27619 and binutils #14758.
This works out fine for the most common case (word-aligned ld), but not
for most others. This patch disables all lwa insns in 32-bit mode.
We can later re-enable it if the assembler used handles it properly,
and for lwax and lwaux, and fix the various ld patterns as well, but
this is at least a small step in the right direction.
gcc:
-# of expected passes 108499
-# of unexpected failures 303
+# of expected passes 108508
+# of unexpected failures 295
gfortran:
-# of expected passes 40555
-# of unexpected failures 175
+# of expected passes 40582
+# of unexpected failures 148
The lwa pattern must be below the extsw pattern, because the lwa_operand
predicate allows registers as well. Changing lwa_operand causes other
problems I do not want to deal with right now.
Bootstrapped and tested on powerpc64-linux -m64,-m32,-m32/-mpowerpc64.
Okay to apply?
Segher
2012-10-25 Segher Boessenkool seg...@kernel.crashing.org
gcc/
* config/rs6000/rs6000.md (sign_extend:SI patterns): Split
the memory case off. Merge the two register cases. Change
the condition for the memory case to require 64-bit mode.
---
gcc/config/rs6000/rs6000.md | 22 --
1 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 2625bd7..5ce7963 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -519,18 +519,9 @@ (define_expand extendsidi2
)
(define_insn
- [(set (match_operand:DI 0 gpc_reg_operand =r,r)
- (sign_extend:DI (match_operand:SI 1 lwa_operand m,r)))]
- TARGET_POWERPC64 rs6000_gen_cell_microcode
- @
- lwa%U1%X1 %0,%1
- extsw %0,%1
- [(set_attr type load_ext,exts)])
-
-(define_insn
[(set (match_operand:DI 0 gpc_reg_operand =r)
(sign_extend:DI (match_operand:SI 1 gpc_reg_operand r)))]
- TARGET_POWERPC64 !rs6000_gen_cell_microcode
+ TARGET_POWERPC64
extsw %0,%1
[(set_attr type exts)])
@@ -586,6 +577,17 @@ (define_split
(const_int 0)))]
)
+; The 32-bit ABI has no relocation for DS_LO; the assembler uses a LO instead
+; for the @l an lwa instruction uses, overwriting the low two bits in the
+; opcode. We could do tricky tricks like adding 2 to the offset, but let's
+; not: only allow this instruction in 64-bit mode.
+(define_insn
+ [(set (match_operand:DI 0 gpc_reg_operand =r)
+ (sign_extend:DI (match_operand:SI 1 lwa_operand m)))]
+ TARGET_64BIT rs6000_gen_cell_microcode
+ lwa%U1%X1 %0,%1
+ [(set_attr type load_ext)])
+
(define_expand zero_extendqisi2
[(set (match_operand:SI 0 gpc_reg_operand )
(zero_extend:SI (match_operand:QI 1 gpc_reg_operand )))]
--
1.7.7.6