// Logic operations
 template<size_t BitsY, size_t BitsA>
-value<BitsY> not_u(const value<BitsA> &a) {
-       return a.template zcast<BitsY>().bit_not();
-}
-
-template<size_t BitsY, size_t BitsA>
-value<BitsY> not_s(const value<BitsA> &a) {
-       return a.template scast<BitsY>().bit_not();
-}
-
-template<size_t BitsY, size_t BitsA>
-value<BitsY> logic_not_u(const value<BitsA> &a) {
+value<BitsY> logic_not(const value<BitsA> &a) {
        return value<BitsY> { a ? 0u : 1u };
 }
 
-template<size_t BitsY, size_t BitsA>
-value<BitsY> logic_not_s(const value<BitsA> &a) {
-       return value<BitsY> { a ? 0u : 1u };
+template<size_t BitsY, size_t BitsA, size_t BitsB>
+value<BitsY> logic_and(const value<BitsA> &a, const value<BitsB> &b) {
+       return value<BitsY> { (bool(a) & bool(b)) ? 1u : 0u };
 }
 
-template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_and_u(const value<BitsA> &a) {
-       return value<BitsY> { a.bit_not().is_zero() ? 1u : 0u };
+template<size_t BitsY, size_t BitsA, size_t BitsB>
+value<BitsY> logic_or(const value<BitsA> &a, const value<BitsB> &b) {
+       return value<BitsY> { (bool(a) | bool(b)) ? 1u : 0u };
 }
 
+// Reduction operations
 template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_and_s(const value<BitsA> &a) {
+value<BitsY> reduce_and(const value<BitsA> &a) {
        return value<BitsY> { a.bit_not().is_zero() ? 1u : 0u };
 }
 
 template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_or_u(const value<BitsA> &a) {
-       return value<BitsY> { a ? 1u : 0u };
-}
-
-template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_or_s(const value<BitsA> &a) {
+value<BitsY> reduce_or(const value<BitsA> &a) {
        return value<BitsY> { a ? 1u : 0u };
 }
 
 template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_xor_u(const value<BitsA> &a) {
-       return value<BitsY> { (a.ctpop() % 2) ? 1u : 0u };
-}
-
-template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_xor_s(const value<BitsA> &a) {
+value<BitsY> reduce_xor(const value<BitsA> &a) {
        return value<BitsY> { (a.ctpop() % 2) ? 1u : 0u };
 }
 
 template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_xnor_u(const value<BitsA> &a) {
+value<BitsY> reduce_xnor(const value<BitsA> &a) {
        return value<BitsY> { (a.ctpop() % 2) ? 0u : 1u };
 }
 
 template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_xnor_s(const value<BitsA> &a) {
-       return value<BitsY> { (a.ctpop() % 2) ? 0u : 1u };
+value<BitsY> reduce_bool(const value<BitsA> &a) {
+       return value<BitsY> { a ? 1u : 0u };
 }
 
+// Bitwise operations
 template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_bool_u(const value<BitsA> &a) {
-       return value<BitsY> { a ? 1u : 0u };
+value<BitsY> not_u(const value<BitsA> &a) {
+       return a.template zcast<BitsY>().bit_not();
 }
 
 template<size_t BitsY, size_t BitsA>
-value<BitsY> reduce_bool_s(const value<BitsA> &a) {
-       return value<BitsY> { a ? 1u : 0u };
+value<BitsY> not_s(const value<BitsA> &a) {
+       return a.template scast<BitsY>().bit_not();
 }
 
 template<size_t BitsY, size_t BitsA, size_t BitsB>
        return a.template scast<BitsY>().bit_xor(b.template scast<BitsY>()).bit_not();
 }
 
-template<size_t BitsY, size_t BitsA, size_t BitsB>
-value<BitsY> logic_and_uu(const value<BitsA> &a, const value<BitsB> &b) {
-       return value<BitsY> { (bool(a) & bool(b)) ? 1u : 0u };
-}
-
-template<size_t BitsY, size_t BitsA, size_t BitsB>
-value<BitsY> logic_and_ss(const value<BitsA> &a, const value<BitsB> &b) {
-       return value<BitsY> { (bool(a) & bool(b)) ? 1u : 0u };
-}
-
-template<size_t BitsY, size_t BitsA, size_t BitsB>
-value<BitsY> logic_or_uu(const value<BitsA> &a, const value<BitsB> &b) {
-       return value<BitsY> { (bool(a) | bool(b)) ? 1u : 0u };
-}
-
-template<size_t BitsY, size_t BitsA, size_t BitsB>
-value<BitsY> logic_or_ss(const value<BitsA> &a, const value<BitsB> &b) {
-       return value<BitsY> { (bool(a) | bool(b)) ? 1u : 0u };
-}
-
 template<size_t BitsY, size_t BitsA, size_t BitsB>
 value<BitsY> shl_uu(const value<BitsA> &a, const value<BitsB> &b) {
        return a.template zcast<BitsY>().template shl(b);
 
                ID($add), ID($sub), ID($mul), ID($div), ID($mod));
 }
 
+bool is_extending_cell(RTLIL::IdString type)
+{
+       return !type.in(
+               ID($logic_not), ID($logic_and), ID($logic_or),
+               ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool));
+}
+
 bool is_elidable_cell(RTLIL::IdString type)
 {
        return is_unary_cell(type) || is_binary_cell(type) || type.in(
        {
                // Unary cells
                if (is_unary_cell(cell->type)) {
-                       f << cell->type.substr(1) << '_' <<
-                            (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u') <<
-                            "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">(";
+                       f << cell->type.substr(1);
+                       if (is_extending_cell(cell->type))
+                               f << '_' << (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u');
+                       f << "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">(";
                        dump_sigspec_rhs(cell->getPort(ID::A));
                        f << ")";
                // Binary cells
                } else if (is_binary_cell(cell->type)) {
-                       f << cell->type.substr(1) << '_' <<
-                            (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u') <<
-                            (cell->getParam(ID::B_SIGNED).as_bool() ? 's' : 'u') <<
-                            "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">(";
+                       f << cell->type.substr(1);
+                       if (is_extending_cell(cell->type))
+                               f << '_' << (cell->getParam(ID::A_SIGNED).as_bool() ? 's' : 'u') <<
+                                           (cell->getParam(ID::B_SIGNED).as_bool() ? 's' : 'u');
+                       f << "<" << cell->getParam(ID::Y_WIDTH).as_int() << ">(";
                        dump_sigspec_rhs(cell->getPort(ID::A));
                        f << ", ";
                        dump_sigspec_rhs(cell->getPort(ID::B));