Index: lib/Target/AArch64/AArch64.td =================================================================== --- lib/Target/AArch64/AArch64.td +++ lib/Target/AArch64/AArch64.td @@ -50,6 +50,10 @@ def FeatureSPE : SubtargetFeature<"spe", "HasSPE", "true", "Enable Statistical Profiling extension">; +// Some targets using CSEL is more prefer than CSINV, CSINC. +def FeatureFastCSEL : SubtargetFeature<"fast-csel", "HasFastCSEL", + "true", "Has fast CSEL">; + /// Cyclone has register move instructions which are "free". def FeatureZCRegMove : SubtargetFeature<"zcm", "HasZeroCycleRegMove", "true", "Has zero-cycle register moves">; Index: lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.td +++ lib/Target/AArch64/AArch64InstrInfo.td @@ -43,6 +43,8 @@ def UseAlternateSExtLoadCVTF32 : Predicate<"Subtarget->useAlternateSExtLoadCVTF32Pattern()">; +def HasSlowCSEL : Predicate<"!Subtarget->hasFastCSEL()">; + //===----------------------------------------------------------------------===// // AArch64-specific DAG Nodes. // @@ -1133,29 +1135,29 @@ (CSINCXr GPR64:$tval, GPR64:$fval, (i32 imm:$cc))>; def : Pat<(AArch64csel (i32 0), (i32 1), (i32 imm:$cc), NZCV), - (CSINCWr WZR, WZR, (i32 imm:$cc))>; + (CSINCWr WZR, WZR, (i32 imm:$cc))>, Requires<[HasSlowCSEL]>; def : Pat<(AArch64csel (i64 0), (i64 1), (i32 imm:$cc), NZCV), - (CSINCXr XZR, XZR, (i32 imm:$cc))>; + (CSINCXr XZR, XZR, (i32 imm:$cc))>, Requires<[HasSlowCSEL]>; def : Pat<(AArch64csel GPR32:$tval, (i32 1), (i32 imm:$cc), NZCV), - (CSINCWr GPR32:$tval, WZR, (i32 imm:$cc))>; + (CSINCWr GPR32:$tval, WZR, (i32 imm:$cc))>, Requires<[HasSlowCSEL]>; def : Pat<(AArch64csel GPR64:$tval, (i64 1), (i32 imm:$cc), NZCV), - (CSINCXr GPR64:$tval, XZR, (i32 imm:$cc))>; + (CSINCXr GPR64:$tval, XZR, (i32 imm:$cc))>, Requires<[HasSlowCSEL]>; def : Pat<(AArch64csel (i32 1), GPR32:$fval, (i32 imm:$cc), NZCV), - (CSINCWr GPR32:$fval, WZR, (i32 (inv_cond_XFORM imm:$cc)))>; + (CSINCWr GPR32:$fval, WZR, (i32 (inv_cond_XFORM imm:$cc)))>, Requires<[HasSlowCSEL]>; def : Pat<(AArch64csel (i64 1), GPR64:$fval, (i32 imm:$cc), NZCV), - (CSINCXr GPR64:$fval, XZR, (i32 (inv_cond_XFORM imm:$cc)))>; + (CSINCXr GPR64:$fval, XZR, (i32 (inv_cond_XFORM imm:$cc)))>, Requires<[HasSlowCSEL]>; def : Pat<(AArch64csel (i32 0), (i32 -1), (i32 imm:$cc), NZCV), - (CSINVWr WZR, WZR, (i32 imm:$cc))>; + (CSINVWr WZR, WZR, (i32 imm:$cc))>, Requires<[HasSlowCSEL]>; def : Pat<(AArch64csel (i64 0), (i64 -1), (i32 imm:$cc), NZCV), - (CSINVXr XZR, XZR, (i32 imm:$cc))>; + (CSINVXr XZR, XZR, (i32 imm:$cc))>, Requires<[HasSlowCSEL]>; def : Pat<(AArch64csel GPR32:$tval, (i32 -1), (i32 imm:$cc), NZCV), - (CSINVWr GPR32:$tval, WZR, (i32 imm:$cc))>; + (CSINVWr GPR32:$tval, WZR, (i32 imm:$cc))>, Requires<[HasSlowCSEL]>; def : Pat<(AArch64csel GPR64:$tval, (i64 -1), (i32 imm:$cc), NZCV), - (CSINVXr GPR64:$tval, XZR, (i32 imm:$cc))>; + (CSINVXr GPR64:$tval, XZR, (i32 imm:$cc))>, Requires<[HasSlowCSEL]>; def : Pat<(AArch64csel (i32 -1), GPR32:$fval, (i32 imm:$cc), NZCV), - (CSINVWr GPR32:$fval, WZR, (i32 (inv_cond_XFORM imm:$cc)))>; + (CSINVWr GPR32:$fval, WZR, (i32 (inv_cond_XFORM imm:$cc)))>, Requires<[HasSlowCSEL]>; def : Pat<(AArch64csel (i64 -1), GPR64:$fval, (i32 imm:$cc), NZCV), - (CSINVXr GPR64:$fval, XZR, (i32 (inv_cond_XFORM imm:$cc)))>; + (CSINVXr GPR64:$fval, XZR, (i32 (inv_cond_XFORM imm:$cc)))>, Requires<[HasSlowCSEL]>; // The inverse of the condition code from the alias instruction is what is used // in the aliased instruction. The parser all ready inverts the condition code Index: lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- lib/Target/AArch64/AArch64Subtarget.h +++ lib/Target/AArch64/AArch64Subtarget.h @@ -76,6 +76,9 @@ // HasZeroCycleZeroing - Has zero-cycle zeroing instructions. bool HasZeroCycleZeroing = false; + // If true, CSEL will be favored over CSINV or CSINC. + bool HasFastCSEL = false; + // StrictAlign - Disallow unaligned memory accesses. bool StrictAlign = false; bool UseAA = false; @@ -179,6 +182,8 @@ bool hasZeroCycleZeroing() const { return HasZeroCycleZeroing; } + bool hasFastCSEL() const { return HasFastCSEL; } + bool requiresStrictAlign() const { return StrictAlign; } bool isXRaySupported() const override { return true; }