[GlobalISel]: Allow targets to override how to widen constants during legalization
https://reviews.llvm.org/D70922
This adds a hook to allow targets to define exactly what extension
operation should be performed for widening constants. This handles cases
like widening i1 true which would end up becoming -1 which affects code
quality during combines.
Additionally, in order to stay consistent with how DAG is promoting
constants, we now signextend for byte sized types and zero extend
otherwise (by default). Targets can of course override this if
necessary.
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
index d184530..642f882 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h
@@ -1157,6 +1157,12 @@
virtual bool legalizeIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &MIRBuilder) const;
+ /// Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while
+ /// widening a constant of type SmallTy which targets can override.
+ /// For eg, the DAG does (SmallTy.isByteSized() ? G_SEXT : G_ZEXT) which
+ /// will be the default.
+ virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const;
+
private:
/// Determine what action should be taken to legalize the given generic
/// instruction opcode, type-index and type. Requires computeTables to have
diff --git a/llvm/include/llvm/Support/LowLevelTypeImpl.h b/llvm/include/llvm/Support/LowLevelTypeImpl.h
index 0e02b6e..6ef7c29 100644
--- a/llvm/include/llvm/Support/LowLevelTypeImpl.h
+++ b/llvm/include/llvm/Support/LowLevelTypeImpl.h
@@ -137,6 +137,8 @@
: LLT::scalar(NewEltSize);
}
+ bool isByteSized() const { return (getSizeInBits() & 7) == 0; }
+
unsigned getScalarSizeInBits() const {
assert(RawData != 0 && "Invalid Type");
if (!IsVector) {
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index d8bcc59..a9af31f 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -1675,7 +1675,15 @@
case TargetOpcode::G_CONSTANT: {
MachineOperand &SrcMO = MI.getOperand(1);
LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
- const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
+ unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
+ MRI.getType(MI.getOperand(0).getReg()));
+ assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
+ ExtOpc == TargetOpcode::G_ANYEXT) &&
+ "Illegal Extend");
+ const APInt &SrcVal = SrcMO.getCImm()->getValue();
+ const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
+ ? SrcVal.sext(WideTy.getSizeInBits())
+ : SrcVal.zext(WideTy.getSizeInBits());
Observer.changingInstr(MI);
SrcMO.setCImm(ConstantInt::get(Ctx, Val));
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp
index 7004551..f897f9c 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp
@@ -685,6 +685,10 @@
return true;
}
+unsigned LegalizerInfo::getExtOpcodeForWideningConstant(LLT SmallTy) const {
+ return SmallTy.isByteSized() ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
+}
+
/// \pre Type indices of every opcode form a dense set starting from 0.
void LegalizerInfo::verify(const MCInstrInfo &MII) const {
#ifndef NDEBUG
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-consts.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-consts.mir
index de55455..9d66209 100644
--- a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-consts.mir
+++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-consts.mir
@@ -44,7 +44,7 @@
%3(s1) = G_CONSTANT i1 1
G_STORE %3(s1), %4(p0) :: (store 1)
; CHECK-NOT: G_CONSTANT i1
- ; CHECK: [[EXT:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+ ; CHECK: [[EXT:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
; CHECK: {{%[0-9]+}}:_(s1) = G_TRUNC [[EXT]](s32)
; CHECK-NOT: G_CONSTANT i1
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir
index b413130..0cdab2c 100644
--- a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir
+++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-fp.mir
@@ -1131,10 +1131,9 @@
; SOFT-NOT: G_FCMP
; For soft float we just need to return a '-1' constant, but the truncation
; to 1 bit is converted by the combiner to the following masking sequence.
- ; SOFT: [[R:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
- ; SOFT: [[MASK:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; SOFT: [[R:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
; SOFT: [[RCOPY:%[0-9]+]]:_(s32) = COPY [[R]](s32)
- ; SOFT: [[REXT:%[0-9]+]]:_(s32) = G_AND [[RCOPY]], [[MASK]]
+ ; SOFT: [[REXT:%[0-9]+]]:_(s32) = G_AND [[RCOPY]], [[R]]
; SOFT-NOT: G_FCMP
; CHECK: $r0 = COPY [[REXT]]
...
@@ -1853,11 +1852,10 @@
; HARD: [[R:%[0-9]+]]:_(s1) = G_FCMP floatpred(true), [[X]](s64), [[Y]]
; HARD: [[REXT:%[0-9]+]]:_(s32) = G_ZEXT [[R]](s1)
; SOFT-NOT: G_FCMP
- ; SOFT: [[R:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
; The result needs to be truncated, and the combiner turns the truncation
; into the following masking sequence.
; SOFT: [[MASK:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
- ; SOFT: [[RCOPY:%[0-9]+]]:_(s32) = COPY [[R]]
+ ; SOFT: [[RCOPY:%[0-9]+]]:_(s32) = COPY [[MASK]]
; SOFT: [[REXT:%[0-9]+]]:_(s32) = G_AND [[RCOPY]], [[MASK]]
; SOFT-NOT: G_FCMP
%7(s32) = G_ZEXT %6(s1)
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/constants.mir b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/constants.mir
index 5a805af..e30870b 100644
--- a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/constants.mir
+++ b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/constants.mir
@@ -131,10 +131,9 @@
body: |
bb.1.entry:
; MIPS32-LABEL: name: i1_true
- ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
- ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY [[C]](s32)
- ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C1]]
+ ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]]
; MIPS32: $v0 = COPY [[AND]](s32)
; MIPS32: RetRA implicit $v0
%0:_(s1) = G_CONSTANT i1 true
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/select.mir b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/select.mir
index 59d4280..057abae 100644
--- a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/select.mir
+++ b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/select.mir
@@ -150,14 +150,13 @@
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2
; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3
- ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+ ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
; MIPS32: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY]](s32), [[COPY1]]
; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ICMP]](s32)
; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY [[C]](s32)
; MIPS32: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[COPY4]], [[COPY5]]
- ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
; MIPS32: [[COPY6:%[0-9]+]]:_(s32) = COPY [[XOR]](s32)
- ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY6]], [[C1]]
+ ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY6]], [[C]]
; MIPS32: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[AND]](s32), [[COPY2]], [[COPY3]]
; MIPS32: $v0 = COPY [[SELECT]](s32)
; MIPS32: RetRA implicit $v0
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/constants.ll b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/constants.ll
index bdafe26..0187b72 100644
--- a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/constants.ll
+++ b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/constants.ll
@@ -71,7 +71,7 @@
define zeroext i1 @i1_true() {
; MIPS32-LABEL: i1_true:
; MIPS32: # %bb.0: # %entry
-; MIPS32-NEXT: addiu $1, $zero, 65535
+; MIPS32-NEXT: ori $1, $zero, 1
; MIPS32-NEXT: andi $2, $1, 1
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/fcmp.ll b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/fcmp.ll
index 8f55963..58d5c8a 100644
--- a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/fcmp.ll
+++ b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/fcmp.ll
@@ -15,7 +15,7 @@
define i1 @true_s(float %x, float %y) {
; MIPS32-LABEL: true_s:
; MIPS32: # %bb.0: # %entry
-; MIPS32-NEXT: addiu $2, $zero, 65535
+; MIPS32-NEXT: ori $2, $zero, 1
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
@@ -233,7 +233,7 @@
define i1 @true_d(double %x, double %y) {
; MIPS32-LABEL: true_d:
; MIPS32: # %bb.0: # %entry
-; MIPS32-NEXT: addiu $2, $zero, 65535
+; MIPS32-NEXT: ori $2, $zero, 1
; MIPS32-NEXT: jr $ra
; MIPS32-NEXT: nop
entry:
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/select.ll b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/select.ll
index c127d12..71c3023 100644
--- a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/select.ll
+++ b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/select.ll
@@ -56,8 +56,9 @@
define i32 @select_with_negation(i32 %a, i32 %b, i32 %x, i32 %y) {
; MIPS32-LABEL: select_with_negation:
; MIPS32: # %bb.0: # %entry
-; MIPS32-NEXT: slt $1, $4, $5
-; MIPS32-NEXT: not $1, $1
+; MIPS32-NEXT: ori $1, $zero, 1
+; MIPS32-NEXT: slt $2, $4, $5
+; MIPS32-NEXT: xor $1, $2, $1
; MIPS32-NEXT: andi $1, $1, 1
; MIPS32-NEXT: movn $7, $6, $1
; MIPS32-NEXT: move $2, $7
diff --git a/llvm/test/CodeGen/X86/GlobalISel/ashr-scalar.ll b/llvm/test/CodeGen/X86/GlobalISel/ashr-scalar.ll
index c24845e..849cf0d 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/ashr-scalar.ll
+++ b/llvm/test/CodeGen/X86/GlobalISel/ashr-scalar.ll
@@ -165,7 +165,7 @@
; X64-LABEL: test_ashr_i1_imm1:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
-; X64-NEXT: movb $-1, %cl
+; X64-NEXT: movb $1, %cl
; X64-NEXT: shlb $7, %al
; X64-NEXT: sarb $7, %al
; X64-NEXT: andb $1, %cl
diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-constant.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-constant.mir
index 3b4bec6..b89116e 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/legalize-constant.mir
+++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-constant.mir
@@ -18,7 +18,7 @@
body: |
bb.1 (%ir-block.0):
; X32-LABEL: name: test_constant
- ; X32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+ ; X32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
; X32: $eax = COPY [[C]](s32)
; X32: [[C1:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
; X32: $al = COPY [[C1]](s8)
@@ -32,7 +32,7 @@
; X32: $rax = COPY [[MV]](s64)
; X32: RET 0
; X64-LABEL: name: test_constant
- ; X64: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+ ; X64: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
; X64: $eax = COPY [[C]](s32)
; X64: [[C1:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
; X64: $al = COPY [[C1]](s8)
diff --git a/llvm/test/CodeGen/X86/GlobalISel/lshr-scalar.ll b/llvm/test/CodeGen/X86/GlobalISel/lshr-scalar.ll
index e935c1c..5dd5375 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/lshr-scalar.ll
+++ b/llvm/test/CodeGen/X86/GlobalISel/lshr-scalar.ll
@@ -164,7 +164,7 @@
; X64-LABEL: test_lshr_i1_imm1:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
-; X64-NEXT: movb $-1, %cl
+; X64-NEXT: movb $1, %cl
; X64-NEXT: andb $1, %al
; X64-NEXT: andb $1, %cl
; X64-NEXT: shrb %cl, %al
diff --git a/llvm/test/CodeGen/X86/GlobalISel/shl-scalar.ll b/llvm/test/CodeGen/X86/GlobalISel/shl-scalar.ll
index 49aa99e..5ccc0ee 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/shl-scalar.ll
+++ b/llvm/test/CodeGen/X86/GlobalISel/shl-scalar.ll
@@ -162,7 +162,7 @@
; X64-LABEL: test_shl_i1_imm1:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
-; X64-NEXT: movb $-1, %cl
+; X64-NEXT: movb $1, %cl
; X64-NEXT: andb $1, %cl
; X64-NEXT: shlb %cl, %al
; X64-NEXT: # kill: def $al killed $al killed $eax