1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use crate::cdsl::settings::{PredicateNode, SettingGroup, SettingGroupBuilder};

pub(crate) fn define(shared: &SettingGroup) -> SettingGroup {
    let mut settings = SettingGroupBuilder::new("x86");

    settings.add_bool(
        "use_new_backend",
        "Whether to use the new codegen backend using the new isel",
        false,
    );

    // CPUID.01H:ECX
    let has_sse3 = settings.add_bool("has_sse3", "SSE3: CPUID.01H:ECX.SSE3[bit 0]", false);
    let has_ssse3 = settings.add_bool("has_ssse3", "SSSE3: CPUID.01H:ECX.SSSE3[bit 9]", false);
    let has_sse41 = settings.add_bool("has_sse41", "SSE4.1: CPUID.01H:ECX.SSE4_1[bit 19]", false);
    let has_sse42 = settings.add_bool("has_sse42", "SSE4.2: CPUID.01H:ECX.SSE4_2[bit 20]", false);
    let has_avx = settings.add_bool("has_avx", "AVX: CPUID.01H:ECX.AVX[bit 28]", false);
    let has_avx2 = settings.add_bool("has_avx2", "AVX2: CPUID.07H:EBX.AVX2[bit 5]", false);
    let has_avx512dq = settings.add_bool(
        "has_avx512dq",
        "AVX512DQ: CPUID.07H:EBX.AVX512DQ[bit 17]",
        false,
    );
    let has_avx512vl = settings.add_bool(
        "has_avx512vl",
        "AVX512DQ: CPUID.07H:EBX.AVX512VL[bit 31]",
        false,
    );
    let has_popcnt = settings.add_bool("has_popcnt", "POPCNT: CPUID.01H:ECX.POPCNT[bit 23]", false);

    // CPUID.(EAX=07H, ECX=0H):EBX
    let has_bmi1 = settings.add_bool(
        "has_bmi1",
        "BMI1: CPUID.(EAX=07H, ECX=0H):EBX.BMI1[bit 3]",
        false,
    );
    let has_bmi2 = settings.add_bool(
        "has_bmi2",
        "BMI2: CPUID.(EAX=07H, ECX=0H):EBX.BMI2[bit 8]",
        false,
    );

    // CPUID.EAX=80000001H:ECX
    let has_lzcnt = settings.add_bool(
        "has_lzcnt",
        "LZCNT: CPUID.EAX=80000001H:ECX.LZCNT[bit 5]",
        false,
    );

    let shared_enable_simd = shared.get_bool("enable_simd");

    settings.add_predicate("use_ssse3", predicate!(has_ssse3));
    settings.add_predicate("use_sse41", predicate!(has_sse41));
    settings.add_predicate("use_sse42", predicate!(has_sse41 && has_sse42));

    settings.add_predicate(
        "use_ssse3_simd",
        predicate!(shared_enable_simd && has_ssse3),
    );
    settings.add_predicate(
        "use_sse41_simd",
        predicate!(shared_enable_simd && has_sse41),
    );
    settings.add_predicate(
        "use_sse42_simd",
        predicate!(shared_enable_simd && has_sse41 && has_sse42),
    );

    settings.add_predicate("use_avx_simd", predicate!(shared_enable_simd && has_avx));
    settings.add_predicate("use_avx2_simd", predicate!(shared_enable_simd && has_avx2));
    settings.add_predicate(
        "use_avx512dq_simd",
        predicate!(shared_enable_simd && has_avx512dq),
    );
    settings.add_predicate(
        "use_avx512vl_simd",
        predicate!(shared_enable_simd && has_avx512vl),
    );

    settings.add_predicate("use_popcnt", predicate!(has_popcnt && has_sse42));
    settings.add_predicate("use_bmi1", predicate!(has_bmi1));
    settings.add_predicate("use_lzcnt", predicate!(has_lzcnt));

    // Some shared boolean values are used in x86 instruction predicates, so we need to group them
    // in the same TargetIsa, for compabitibity with code generated by meta-python.
    // TODO Once all the meta generation code has been migrated from Python to Rust, we can put it
    // back in the shared SettingGroup, and use it in x86 instruction predicates.

    let is_pic = shared.get_bool("is_pic");
    let emit_all_ones_funcaddrs = shared.get_bool("emit_all_ones_funcaddrs");
    settings.add_predicate("is_pic", predicate!(is_pic));
    settings.add_predicate("not_is_pic", predicate!(!is_pic));
    settings.add_predicate(
        "all_ones_funcaddrs_and_not_is_pic",
        predicate!(emit_all_ones_funcaddrs && !is_pic),
    );
    settings.add_predicate(
        "not_all_ones_funcaddrs_and_not_is_pic",
        predicate!(!emit_all_ones_funcaddrs && !is_pic),
    );

    // Presets corresponding to x86 CPUs.

    settings.add_preset("baseline", preset!());
    let nehalem = settings.add_preset(
        "nehalem",
        preset!(has_sse3 && has_ssse3 && has_sse41 && has_sse42 && has_popcnt),
    );
    let haswell = settings.add_preset(
        "haswell",
        preset!(nehalem && has_bmi1 && has_bmi2 && has_lzcnt),
    );
    let broadwell = settings.add_preset("broadwell", preset!(haswell));
    let skylake = settings.add_preset("skylake", preset!(broadwell));
    let cannonlake = settings.add_preset("cannonlake", preset!(skylake));
    settings.add_preset("icelake", preset!(cannonlake));
    settings.add_preset(
        "znver1",
        preset!(
            has_sse3
                && has_ssse3
                && has_sse41
                && has_sse42
                && has_popcnt
                && has_bmi1
                && has_bmi2
                && has_lzcnt
        ),
    );

    settings.build()
}