diff options
Diffstat (limited to 'recipes-devtools/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch')
| -rw-r--r-- | recipes-devtools/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/recipes-devtools/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch b/recipes-devtools/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch new file mode 100644 index 00000000..4da74f3f --- /dev/null +++ b/recipes-devtools/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch | |||
| @@ -0,0 +1,224 @@ | |||
| 1 | From: David Holsgrove <david.holsgrove@xilinx.com> | ||
| 2 | Subject: [PATCH 8/8] [Patch, microblaze]: Add branch_compare instruction | ||
| 3 | |||
| 4 | To facilitate optimization pass understanding of the conditional | ||
| 5 | branch for microblaze, remove the UNSPEC'd signed_compare / | ||
| 6 | unsigned_compare instructions, and replace with a complete | ||
| 7 | branch_compare which will output_asm_insn the correct cmp/cmpu | ||
| 8 | depending on comparison code and signed / unsigned. | ||
| 9 | |||
| 10 | We then return the correct branch instruction. | ||
| 11 | |||
| 12 | cbranchsi now calls an expanded microblaze_expand_conditional_branch | ||
| 13 | function which will carry out compare against zero, compare EQ/NE, | ||
| 14 | and all other compares appropriately. | ||
| 15 | |||
| 16 | -funroll-loops optimization pass can now proceed | ||
| 17 | |||
| 18 | Changelog | ||
| 19 | |||
| 20 | 2013-03-19 David Holsgrove <david.holsgrove@xilinx.com> | ||
| 21 | |||
| 22 | * gcc/config/microblaze/predicates.md: Add cmp_op predicate. | ||
| 23 | * gcc/config/microblaze/microblaze.md: Add branch_compare | ||
| 24 | instruction which uses cmp_op predicate and emits cmp insn | ||
| 25 | before branch. | ||
| 26 | * gcc/config/microblaze/microblaze.c | ||
| 27 | (microblaze_emit_compare): Rename to | ||
| 28 | microblaze_expand_conditional_branch and consolidate logic. | ||
| 29 | (microblaze_expand_conditional_branch): emit branch_compare | ||
| 30 | insn instead of handling cmp op separate from branch insn. | ||
| 31 | |||
| 32 | Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com> | ||
| 33 | Upstream-Status: Pending | ||
| 34 | |||
| 35 | diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c | ||
| 36 | index 4417289..84b58bf 100644 | ||
| 37 | --- a/gcc/config/microblaze/microblaze.c | ||
| 38 | +++ b/gcc/config/microblaze/microblaze.c | ||
| 39 | @@ -3336,65 +3336,45 @@ microblaze_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) | ||
| 40 | emit_move_insn (mem, fnaddr); | ||
| 41 | } | ||
| 42 | |||
| 43 | -/* Emit instruction to perform compare. | ||
| 44 | - cmp is (compare_op op0 op1). */ | ||
| 45 | -static rtx | ||
| 46 | -microblaze_emit_compare (enum machine_mode mode, rtx cmp, enum rtx_code *cmp_code) | ||
| 47 | +/* Generate conditional branch -- first, generate test condition, | ||
| 48 | + second, generate correct branch instruction. */ | ||
| 49 | + | ||
| 50 | +void | ||
| 51 | +microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[]) | ||
| 52 | { | ||
| 53 | - rtx cmp_op0 = XEXP (cmp, 0); | ||
| 54 | - rtx cmp_op1 = XEXP (cmp, 1); | ||
| 55 | + enum rtx_code code = GET_CODE (operands[0]); | ||
| 56 | + rtx cmp_op0 = operands[1]; | ||
| 57 | + rtx cmp_op1 = operands[2]; | ||
| 58 | + rtx label1 = operands[3]; | ||
| 59 | rtx comp_reg = gen_reg_rtx (SImode); | ||
| 60 | - enum rtx_code code = *cmp_code; | ||
| 61 | - | ||
| 62 | + rtx condition; | ||
| 63 | + | ||
| 64 | gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG)); | ||
| 65 | |||
| 66 | /* If comparing against zero, just test source reg. */ | ||
| 67 | - if (cmp_op1 == const0_rtx) | ||
| 68 | - return cmp_op0; | ||
| 69 | + if (cmp_op1 == const0_rtx) | ||
| 70 | + { | ||
| 71 | + comp_reg = cmp_op0; | ||
| 72 | + condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx); | ||
| 73 | + emit_jump_insn (gen_condjump (condition, label1)); | ||
| 74 | + } | ||
| 75 | |||
| 76 | - if (code == EQ || code == NE) | ||
| 77 | + else if (code == EQ || code == NE) | ||
| 78 | { | ||
| 79 | /* Use xor for equal/not-equal comparison. */ | ||
| 80 | emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1)); | ||
| 81 | + condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx); | ||
| 82 | + emit_jump_insn (gen_condjump (condition, label1)); | ||
| 83 | } | ||
| 84 | - else if (code == GT || code == GTU || code == LE || code == LEU) | ||
| 85 | - { | ||
| 86 | - /* MicroBlaze compare is not symmetrical. */ | ||
| 87 | - /* Swap argument order. */ | ||
| 88 | - cmp_op1 = force_reg (mode, cmp_op1); | ||
| 89 | - if (code == GT || code == LE) | ||
| 90 | - emit_insn (gen_signed_compare (comp_reg, cmp_op0, cmp_op1)); | ||
| 91 | - else | ||
| 92 | - emit_insn (gen_unsigned_compare (comp_reg, cmp_op0, cmp_op1)); | ||
| 93 | - /* Translate test condition. */ | ||
| 94 | - *cmp_code = swap_condition (code); | ||
| 95 | - } | ||
| 96 | - else /* if (code == GE || code == GEU || code == LT || code == LTU) */ | ||
| 97 | + else | ||
| 98 | { | ||
| 99 | + /* Generate compare and branch in single instruction. */ | ||
| 100 | cmp_op1 = force_reg (mode, cmp_op1); | ||
| 101 | - if (code == GE || code == LT) | ||
| 102 | - emit_insn (gen_signed_compare (comp_reg, cmp_op1, cmp_op0)); | ||
| 103 | - else | ||
| 104 | - emit_insn (gen_unsigned_compare (comp_reg, cmp_op1, cmp_op0)); | ||
| 105 | + condition = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1); | ||
| 106 | + emit_jump_insn (gen_branch_compare(condition, cmp_op0, cmp_op1, label1)); | ||
| 107 | } | ||
| 108 | - | ||
| 109 | - return comp_reg; | ||
| 110 | } | ||
| 111 | |||
| 112 | -/* Generate conditional branch -- first, generate test condition, | ||
| 113 | - second, generate correct branch instruction. */ | ||
| 114 | - | ||
| 115 | -void | ||
| 116 | -microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[]) | ||
| 117 | -{ | ||
| 118 | - enum rtx_code code = GET_CODE (operands[0]); | ||
| 119 | - rtx comp; | ||
| 120 | - rtx condition; | ||
| 121 | - | ||
| 122 | - comp = microblaze_emit_compare (mode, operands[0], &code); | ||
| 123 | - condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp, const0_rtx); | ||
| 124 | - emit_jump_insn (gen_condjump (condition, operands[3])); | ||
| 125 | -} | ||
| 126 | |||
| 127 | void | ||
| 128 | microblaze_expand_conditional_branch_sf (rtx operands[]) | ||
| 129 | diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md | ||
| 130 | index 49d8f01..9c1e1a3 100644 | ||
| 131 | --- a/gcc/config/microblaze/microblaze.md | ||
| 132 | +++ b/gcc/config/microblaze/microblaze.md | ||
| 133 | @@ -1624,28 +1624,6 @@ | ||
| 134 | (set_attr "length" "4")] | ||
| 135 | ) | ||
| 136 | |||
| 137 | -(define_insn "signed_compare" | ||
| 138 | - [(set (match_operand:SI 0 "register_operand" "=d") | ||
| 139 | - (unspec | ||
| 140 | - [(match_operand:SI 1 "register_operand" "d") | ||
| 141 | - (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMP))] | ||
| 142 | - "" | ||
| 143 | - "cmp\t%0,%1,%2" | ||
| 144 | - [(set_attr "type" "arith") | ||
| 145 | - (set_attr "mode" "SI") | ||
| 146 | - (set_attr "length" "4")]) | ||
| 147 | - | ||
| 148 | -(define_insn "unsigned_compare" | ||
| 149 | - [(set (match_operand:SI 0 "register_operand" "=d") | ||
| 150 | - (unspec | ||
| 151 | - [(match_operand:SI 1 "register_operand" "d") | ||
| 152 | - (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMPU))] | ||
| 153 | - "" | ||
| 154 | - "cmpu\t%0,%1,%2" | ||
| 155 | - [(set_attr "type" "arith") | ||
| 156 | - (set_attr "mode" "SI") | ||
| 157 | - (set_attr "length" "4")]) | ||
| 158 | - | ||
| 159 | ;;---------------------------------------------------------------- | ||
| 160 | ;; Setting a register from an floating point comparison. | ||
| 161 | ;;---------------------------------------------------------------- | ||
| 162 | @@ -1719,6 +1697,47 @@ | ||
| 163 | (set_attr "length" "4")] | ||
| 164 | ) | ||
| 165 | |||
| 166 | +(define_insn "branch_compare" | ||
| 167 | + [(set (pc) | ||
| 168 | + (if_then_else (match_operator:SI 0 "cmp_op" | ||
| 169 | + [(match_operand:SI 1 "register_operand" "d") | ||
| 170 | + (match_operand:SI 2 "register_operand" "d") | ||
| 171 | + ]) | ||
| 172 | + (label_ref (match_operand 3)) | ||
| 173 | + (pc))) | ||
| 174 | + (clobber(reg:SI R_TMP))] | ||
| 175 | + "" | ||
| 176 | + { | ||
| 177 | + operands[4] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); | ||
| 178 | + enum rtx_code code = GET_CODE (operands[0]); | ||
| 179 | + | ||
| 180 | + if (code == GT || code == LE) | ||
| 181 | + { | ||
| 182 | + output_asm_insn ("cmp\tr18,%z1,%z2", operands); | ||
| 183 | + code = swap_condition (code); | ||
| 184 | + } | ||
| 185 | + else if (code == GTU || code == LEU) | ||
| 186 | + { | ||
| 187 | + output_asm_insn ("cmpu\tr18,%z1,%z2", operands); | ||
| 188 | + code = swap_condition (code); | ||
| 189 | + } | ||
| 190 | + else if (code == GE || code == LT) | ||
| 191 | + { | ||
| 192 | + output_asm_insn ("cmp\tr18,%z2,%z1", operands); | ||
| 193 | + } | ||
| 194 | + else if (code == GEU || code == LTU) | ||
| 195 | + { | ||
| 196 | + output_asm_insn ("cmpu\tr18,%z2,%z1", operands); | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx); | ||
| 200 | + return "b%C0i%?\tr18,%3"; | ||
| 201 | + } | ||
| 202 | + [(set_attr "type" "branch") | ||
| 203 | + (set_attr "mode" "none") | ||
| 204 | + (set_attr "length" "12")] | ||
| 205 | +) | ||
| 206 | + | ||
| 207 | ;;---------------------------------------------------------------- | ||
| 208 | ;; Unconditional branches | ||
| 209 | ;;---------------------------------------------------------------- | ||
| 210 | diff --git a/gcc/config/microblaze/predicates.md b/gcc/config/microblaze/predicates.md | ||
| 211 | index 5fd1bd4..2c23291 100644 | ||
| 212 | --- a/gcc/config/microblaze/predicates.md | ||
| 213 | +++ b/gcc/config/microblaze/predicates.md | ||
| 214 | @@ -119,3 +119,7 @@ | ||
| 215 | ;; Test for valid PIC call operand | ||
| 216 | (define_predicate "call_insn_plt_operand" | ||
| 217 | (match_test "PLT_ADDR_P (op)")) | ||
| 218 | + | ||
| 219 | +;; Return if the code of this rtx pattern is a comparison. | ||
| 220 | +(define_predicate "cmp_op" | ||
| 221 | + (match_code "gt,ge,gtu,geu,lt,le,ltu,leu")) | ||
| 222 | -- | ||
| 223 | 1.7.5.4 | ||
| 224 | |||
